about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/documentation.yaml12
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs29
-rw-r--r--compiler/rustc_borrowck/src/polonius/constraints.rs4
-rw-r--r--compiler/rustc_borrowck/src/polonius/liveness_constraints.rs12
-rw-r--r--compiler/rustc_borrowck/src/polonius/loan_liveness.rs191
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/polonius/typeck_constraints.rs19
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs7
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs16
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs4
-rw-r--r--compiler/rustc_type_ir/src/binder.rs21
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs24
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs8
-rw-r--r--compiler/rustc_type_ir/src/error.rs4
-rw-r--r--compiler/rustc_type_ir/src/generic_arg.rs8
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs4
-rw-r--r--compiler/rustc_type_ir/src/opaque_ty.rs4
-rw-r--r--compiler/rustc_type_ir/src/pattern.rs4
-rw-r--r--compiler/rustc_type_ir/src/predicate.rs54
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs8
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs4
-rw-r--r--compiler/rustc_type_ir/src/relate.rs4
-rw-r--r--compiler/rustc_type_ir/src/solve/inspect.rs31
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs37
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs32
-rw-r--r--compiler/rustc_type_ir/src/ty_kind/closure.rs19
-rw-r--r--library/alloc/src/collections/btree/map.rs2
-rw-r--r--library/core/src/time.rs8
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--library/std/src/collections/hash/map.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs7
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs9
-rw-r--r--src/bootstrap/src/utils/exec.rs165
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md5
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md11
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md6
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/TERM.md5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/terminal-urls.md13
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md5
-rw-r--r--src/doc/unstable-book/src/library-features/duration-constructors-lite.md11
-rw-r--r--src/doc/unstable-book/src/library-features/duration-constructors.md1
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs2
-rw-r--r--src/tools/tidy/src/features.rs35
-rw-r--r--src/tools/tidy/src/unstable_book.rs2
-rw-r--r--src/tools/unstable-book-gen/src/main.rs29
-rw-r--r--src/tools/unstable-book-gen/src/stub-env-var.md9
-rw-r--r--tests/assembly-llvm/asm/loongarch-type.rs51
-rw-r--r--tests/crashes/135646.rs7
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/exporter.def2
-rw-r--r--tests/run-make/raw-dylib-link-ordinal/rmake.rs3
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr38
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr62
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr12
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr20
-rw-r--r--tests/ui/asm/loongarch/bad-reg.rs15
-rw-r--r--tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs (renamed from tests/ui/issues/issue-15783.rs)2
-rw-r--r--tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr (renamed from tests/ui/issues/issue-15783.stderr)4
-rw-r--r--tests/ui/closures/unused-closure-ice-16256.rs (renamed from tests/ui/issues/issue-16256.rs)2
-rw-r--r--tests/ui/closures/unused-closure-ice-16256.stderr (renamed from tests/ui/issues/issue-16256.stderr)2
-rw-r--r--tests/ui/codegen/nested-enum-match-optimization-15793.rs (renamed from tests/ui/issues/issue-15793.rs)2
-rw-r--r--tests/ui/derives/derive-partial-ord-discriminant-64bit.rs (renamed from tests/ui/issues/issue-15523-big.rs)3
-rw-r--r--tests/ui/derives/derive-partial-ord-discriminant.rs (renamed from tests/ui/issues/issue-15523.rs)2
-rw-r--r--tests/ui/drop/dropck-normalize-errors.nll.stderr (renamed from tests/ui/drop/dropck-normalize-errors.stderr)24
-rw-r--r--tests/ui/drop/dropck-normalize-errors.polonius.stderr64
-rw-r--r--tests/ui/drop/dropck-normalize-errors.rs6
-rw-r--r--tests/ui/drop/enum-drop-impl-15063.rs (renamed from tests/ui/issues/issue-15063.rs)2
-rw-r--r--tests/ui/drop/generic-drop-trait-bound-15858.rs (renamed from tests/ui/issues/issue-15858.rs)2
-rw-r--r--tests/ui/drop/generic-drop-trait-bound-15858.stderr (renamed from tests/ui/issues/issue-15858.stderr)2
-rw-r--r--tests/ui/drop/nested-return-drop-order.rs (renamed from tests/ui/issues/issue-15763.rs)2
-rw-r--r--tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs34
-rw-r--r--tests/ui/drop/struct-field-drop-order.rs (renamed from tests/ui/issues/issue-16492.rs)2
-rw-r--r--tests/ui/extern/empty-struct-extern-fn-16441.rs (renamed from tests/ui/issues/issue-16441.rs)2
-rw-r--r--tests/ui/fn/fn-traits-call-once-signature-15094.rs (renamed from tests/ui/issues/issue-15094.rs)2
-rw-r--r--tests/ui/fn/fn-traits-call-once-signature-15094.stderr (renamed from tests/ui/issues/issue-15094.stderr)2
-rw-r--r--tests/ui/imports/enum-variant-import-path-15774.rs (renamed from tests/ui/issues/issue-15774.rs)2
-rw-r--r--tests/ui/inference/iterator-sum-array-15673.rs11
-rw-r--r--tests/ui/inference/return-block-type-inference-15965.rs (renamed from tests/ui/issues/issue-15965.rs)2
-rw-r--r--tests/ui/inference/return-block-type-inference-15965.stderr (renamed from tests/ui/issues/issue-15965.stderr)2
-rw-r--r--tests/ui/iterators/explicit-deref-non-deref-type-15756.rs (renamed from tests/ui/issues/issue-15756.rs)2
-rw-r--r--tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr (renamed from tests/ui/issues/issue-15756.stderr)2
-rw-r--r--tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs (renamed from tests/ui/issues/issue-15034.rs)2
-rw-r--r--tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr (renamed from tests/ui/issues/issue-15034.stderr)2
-rw-r--r--tests/ui/lifetimes/struct-lifetime-inference-15735.rs19
-rw-r--r--tests/ui/macros/for-loop-macro-rules-hygiene.rs (renamed from tests/ui/issues/issue-15189.rs)2
-rw-r--r--tests/ui/macros/macro-hygiene-scope-15167.rs (renamed from tests/ui/issues/issue-15167.rs)2
-rw-r--r--tests/ui/macros/macro-hygiene-scope-15167.stderr (renamed from tests/ui/issues/issue-15167.stderr)8
-rw-r--r--tests/ui/moves/match-move-same-binding-15571.rs (renamed from tests/ui/issues/issue-15571.rs)2
-rw-r--r--tests/ui/moves/use-correct-generic-args-in-borrow-suggest.rs13
-rw-r--r--tests/ui/moves/use-correct-generic-args-in-borrow-suggest.stderr18
-rw-r--r--tests/ui/never/never-type-method-call-15207.rs (renamed from tests/ui/issues/issue-15207.rs)2
-rw-r--r--tests/ui/never/never-type-method-call-15207.stderr (renamed from tests/ui/issues/issue-15207.stderr)2
-rw-r--r--tests/ui/nll/issue-46589.nll.stderr2
-rw-r--r--tests/ui/nll/issue-46589.polonius.stderr15
-rw-r--r--tests/ui/nll/issue-46589.rs12
-rw-r--r--tests/ui/nll/polonius/array-literal-index-oob-2024.rs12
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.rs34
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr2
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr12
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr4
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr22
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr2
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr18
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr15
-rw-r--r--tests/ui/nll/polonius/iterating-updating-mutref.rs87
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr26
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.rs71
-rw-r--r--tests/ui/parser/generics-rangle-eq-15043.rs (renamed from tests/ui/issues/issue-15043.rs)2
-rw-r--r--tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs (renamed from tests/ui/issues/issue-15896.rs)2
-rw-r--r--tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr (renamed from tests/ui/issues/issue-15896.stderr)2
-rw-r--r--tests/ui/pattern/refutable-pattern-for-loop-15381.rs (renamed from tests/ui/issues/issue-15381.rs)2
-rw-r--r--tests/ui/pattern/refutable-pattern-for-loop-15381.stderr (renamed from tests/ui/issues/issue-15381.stderr)2
-rw-r--r--tests/ui/pattern/slice-pattern-recursion-15104.rs (renamed from tests/ui/issues/issue-15104.rs)2
-rw-r--r--tests/ui/pattern/static-binding-shadow-16149.rs (renamed from tests/ui/issues/issue-16149.rs)2
-rw-r--r--tests/ui/pattern/static-binding-shadow-16149.stderr (renamed from tests/ui/issues/issue-16149.stderr)2
-rw-r--r--tests/ui/pattern/struct-field-duplicate-binding-15260.rs (renamed from tests/ui/issues/issue-15260.rs)2
-rw-r--r--tests/ui/pattern/struct-field-duplicate-binding-15260.stderr (renamed from tests/ui/issues/issue-15260.stderr)8
-rw-r--r--tests/ui/pattern/tuple-enum-match-15129.rs (renamed from tests/ui/issues/issue-15129-rpass.rs)13
-rw-r--r--tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs (renamed from tests/ui/issues/issue-16401.rs)2
-rw-r--r--tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr (renamed from tests/ui/issues/issue-16401.stderr)2
-rw-r--r--tests/ui/statics/conditional-static-declaration-16010.rs (renamed from tests/ui/issues/issue-16452.rs)2
-rw-r--r--tests/ui/traits/fn-type-trait-impl-15444.rs (renamed from tests/ui/issues/issue-15444.rs)2
-rw-r--r--tests/ui/traits/index-trait-multiple-impls-15734.rs (renamed from tests/ui/issues/issue-15734.rs)2
-rw-r--r--tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs (renamed from tests/ui/issues/issue-16048.rs)2
-rw-r--r--tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr (renamed from tests/ui/issues/issue-16048.stderr)4
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.nll.stderr (renamed from tests/ui/wf/hir-wf-check-erase-regions.stderr)8
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr39
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.rs6
-rw-r--r--triagebot.toml2
143 files changed, 1412 insertions, 561 deletions
diff --git a/.github/ISSUE_TEMPLATE/documentation.yaml b/.github/ISSUE_TEMPLATE/documentation.yaml
index 712b32759ae..4a79cd4ba97 100644
--- a/.github/ISSUE_TEMPLATE/documentation.yaml
+++ b/.github/ISSUE_TEMPLATE/documentation.yaml
@@ -1,5 +1,5 @@
 name: Documentation problem
-description: Create a report for a documentation problem.
+description: Report an issue with documentation content.
 labels: ["A-docs"]
 body:
   - type: markdown
@@ -19,20 +19,20 @@ body:
         - [The Rustonomicon](https://github.com/rust-lang/nomicon/issues)
         - [The Embedded Book](https://github.com/rust-embedded/book/issues)
 
-        All other documentation issues should be filed here.
+        Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the rustdoc issue template instead.
 
-        Or, if you find an issue related to rustdoc (e.g. doctest, rustdoc UI), please use the bug report or blank issue template instead.
+        All other documentation issues should be filed here.
 
   - type: textarea
     id: location
     attributes:
-      label: Location
+      label: Location (URL)
     validations:
-      required: true 
+      required: true
 
   - type: textarea
     id: summary
     attributes:
       label: Summary
     validations:
-      required: true 
\ No newline at end of file
+      required: true
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index af279e07acc..d44faad017e 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -48,6 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     | asm::InlineAsmArch::Arm64EC
                     | asm::InlineAsmArch::RiscV32
                     | asm::InlineAsmArch::RiscV64
+                    | asm::InlineAsmArch::LoongArch32
                     | asm::InlineAsmArch::LoongArch64
                     | asm::InlineAsmArch::S390x
             );
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index be8b3f0bc1e..7e20a5133e0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -410,18 +410,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 }
                 let typeck = self.infcx.tcx.typeck(self.mir_def_id());
                 let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
-                let (def_id, call_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
+                let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
                     && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
                 {
                     let def_id = typeck.type_dependent_def_id(parent_expr.hir_id);
-                    (def_id, Some(parent_expr.hir_id), args, 1)
+                    (def_id, args, 1)
                 } else if let hir::Node::Expr(parent_expr) = parent
                     && let hir::ExprKind::Call(call, args) = parent_expr.kind
                     && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
                 {
-                    (Some(*def_id), Some(call.hir_id), args, 0)
+                    (Some(*def_id), args, 0)
                 } else {
-                    (None, None, &[][..], 0)
+                    (None, &[][..], 0)
                 };
                 let ty = place.ty(self.body, self.infcx.tcx).ty;
 
@@ -459,11 +459,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     // If the moved place is used generically by the callee and a reference to it
                     // would still satisfy any bounds on its type, suggest borrowing.
                     if let Some(&param) = arg_param
-                        && let Some(generic_args) = call_id.and_then(|id| typeck.node_args_opt(id))
+                        && let hir::Node::Expr(call_expr) = parent
                         && let Some(ref_mutability) = self.suggest_borrow_generic_arg(
                             err,
+                            typeck,
+                            call_expr,
                             def_id,
-                            generic_args,
                             param,
                             moved_place,
                             pos + offset,
@@ -627,8 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     fn suggest_borrow_generic_arg(
         &self,
         err: &mut Diag<'_>,
+        typeck: &ty::TypeckResults<'tcx>,
+        call_expr: &hir::Expr<'tcx>,
         callee_did: DefId,
-        generic_args: ty::GenericArgsRef<'tcx>,
         param: ty::ParamTy,
         moved_place: PlaceRef<'tcx>,
         moved_arg_pos: usize,
@@ -639,6 +641,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
         let clauses = tcx.predicates_of(callee_did);
 
+        let generic_args = match call_expr.kind {
+            // For method calls, generic arguments are attached to the call node.
+            hir::ExprKind::MethodCall(..) => typeck.node_args_opt(call_expr.hir_id)?,
+            // For normal calls, generic arguments are in the callee's type.
+            // This diagnostic is only run for `FnDef` callees.
+            hir::ExprKind::Call(callee, _)
+                if let &ty::FnDef(_, args) = typeck.node_type(callee.hir_id).kind() =>
+            {
+                args
+            }
+            _ => return None,
+        };
+
         // First, is there at least one method on one of `param`'s trait bounds?
         // This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
         if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs
index 50f59dd0dee..52595757859 100644
--- a/compiler/rustc_borrowck/src/polonius/constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/constraints.rs
@@ -7,9 +7,7 @@ use rustc_mir_dataflow::points::PointIndex;
 ///
 /// This models two sources of constraints:
 /// - constraints that traverse the subsets between regions at a given point, `a@p: b@p`. These
-///   depend on typeck constraints generated via assignments, calls, etc. (In practice there are
-///   subtleties where a statement's effect only starts being visible at the successor point, via
-///   the "result" of that statement).
+///   depend on typeck constraints generated via assignments, calls, etc.
 /// - constraints that traverse the CFG via the same region, `a@p: a@q`, where `p` is a predecessor
 ///   of `q`. These depend on the liveness of the regions at these points, as well as their
 ///   variance.
diff --git a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
index 6ab09f731c0..2ba72180d66 100644
--- a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
@@ -105,22 +105,14 @@ fn propagate_loans_between_points(
         });
     }
 
-    let Some(current_live_regions) = live_regions.row(current_point) else {
-        // There are no constraints to add: there are no live regions at the current point.
-        return;
-    };
     let Some(next_live_regions) = live_regions.row(next_point) else {
         // There are no constraints to add: there are no live regions at the next point.
         return;
     };
 
     for region in next_live_regions.iter() {
-        if !current_live_regions.contains(region) {
-            continue;
-        }
-
-        // `region` is indeed live at both points, add a constraint between them, according to
-        // variance.
+        // `region` could be live at the current point, and is live at the next point: add a
+        // constraint between them, according to variance.
         if let Some(&direction) = live_region_variances.get(&region) {
             add_liveness_constraint(
                 region,
diff --git a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
index 5cd265e0db9..bdc3047e5ba 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
@@ -1,27 +1,18 @@
-use std::collections::{BTreeMap, BTreeSet};
-
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{
-    Body, Local, Location, Place, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
-};
-use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_middle::ty::RegionVid;
 use rustc_mir_dataflow::points::PointIndex;
 
 use super::{LiveLoans, LocalizedOutlivesConstraintSet};
+use crate::BorrowSet;
 use crate::constraints::OutlivesConstraint;
-use crate::dataflow::BorrowIndex;
 use crate::region_infer::values::LivenessValues;
 use crate::type_check::Locations;
-use crate::{BorrowSet, PlaceConflictBias, places_conflict};
 
-/// Compute loan reachability, stop at kills, and trace loan liveness throughout the CFG, by
+/// Compute loan reachability to approximately trace loan liveness throughout the CFG, by
 /// traversing the full graph of constraints that combines:
 /// - the localized constraints (the physical edges),
 /// - with the constraints that hold at all points (the logical edges).
 pub(super) fn compute_loan_liveness<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
     liveness: &LivenessValues,
     outlives_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
     borrow_set: &BorrowSet<'tcx>,
@@ -29,11 +20,6 @@ pub(super) fn compute_loan_liveness<'tcx>(
 ) -> LiveLoans {
     let mut live_loans = LiveLoans::new(borrow_set.len());
 
-    // FIXME: it may be preferable for kills to be encoded in the edges themselves, to simplify and
-    // likely make traversal (and constraint generation) more efficient. We also display kills on
-    // edges when visualizing the constraint graph anyways.
-    let kills = collect_kills(body, tcx, borrow_set);
-
     // Create the full graph with the physical edges we've localized earlier, and the logical edges
     // of constraints that hold at all points.
     let logical_constraints =
@@ -59,15 +45,15 @@ pub(super) fn compute_loan_liveness<'tcx>(
                 continue;
             }
 
-            // Record the loan as being live on entry to this point.
-            live_loans.insert(node.point, loan_idx);
-
-            // Here, we have a conundrum. There's currently a weakness in our theory, in that
-            // we're using a single notion of reachability to represent what used to be _two_
-            // different transitive closures. It didn't seem impactful when coming up with the
-            // single-graph and reachability through space (regions) + time (CFG) concepts, but in
-            // practice the combination of time-traveling with kills is more impactful than
-            // initially anticipated.
+            // Record the loan as being live on entry to this point if it reaches a live region
+            // there.
+            //
+            // This is an approximation of liveness (which is the thing we want), in that we're
+            // using a single notion of reachability to represent what used to be _two_ different
+            // transitive closures. It didn't seem impactful when coming up with the single-graph
+            // and reachability through space (regions) + time (CFG) concepts, but in practice the
+            // combination of time-traveling with kills is more impactful than initially
+            // anticipated.
             //
             // Kills should prevent a loan from reaching its successor points in the CFG, but not
             // while time-traveling: we're not actually at that CFG point, but looking for
@@ -92,40 +78,20 @@ pub(super) fn compute_loan_liveness<'tcx>(
             //   two-step traversal described above: only kills encountered on exit via a backward
             //   edge are ignored.
             //
-            // In our test suite, there are a couple of cases where kills are encountered while
-            // time-traveling, however as far as we can tell, always in cases where they would be
-            // unreachable. We have reason to believe that this is a property of the single-graph
-            // approach (but haven't proved it yet):
-            // - reachable kills while time-traveling would also be encountered via regular
-            //   traversal
-            // - it makes _some_ sense to ignore unreachable kills, but subtleties around dead code
-            //   in general need to be better thought through (like they were for NLLs).
-            // - ignoring kills is a conservative approximation: the loan is still live and could
-            //   cause false positive errors at another place access. Soundness issues in this
-            //   domain should look more like the absence of reachability instead.
-            //
-            // This is enough in practice to pass tests, and therefore is what we have implemented
-            // for now.
+            // This version of the analysis, however, is enough in practice to pass the tests that
+            // we care about and NLLs reject, without regressions on crater, and is an actionable
+            // subset of the full analysis. It also naturally points to areas of improvement that we
+            // wish to explore later, namely handling kills appropriately during traversal, instead
+            // of continuing traversal to all the reachable nodes.
             //
-            // FIXME: all of the above. Analyze potential unsoundness, possibly in concert with a
-            // borrowck implementation in a-mir-formality, fuzzing, or manually crafting
-            // counter-examples.
+            // FIXME: analyze potential unsoundness, possibly in concert with a borrowck
+            // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples.
 
-            // Continuing traversal will depend on whether the loan is killed at this point, and
-            // whether we're time-traveling.
-            let current_location = liveness.location_from_point(node.point);
-            let is_loan_killed =
-                kills.get(&current_location).is_some_and(|kills| kills.contains(&loan_idx));
+            if liveness.is_live_at(node.region, liveness.location_from_point(node.point)) {
+                live_loans.insert(node.point, loan_idx);
+            }
 
             for succ in graph.outgoing_edges(node) {
-                // If the loan is killed at this point, it is killed _on exit_. But only during
-                // forward traversal.
-                if is_loan_killed {
-                    let destination = liveness.location_from_point(succ.point);
-                    if current_location.is_predecessor_of(destination, body) {
-                        continue;
-                    }
-                }
                 stack.push(succ);
             }
         }
@@ -192,116 +158,3 @@ impl LocalizedConstraintGraph {
         physical_edges.chain(materialized_edges)
     }
 }
-
-/// Traverses the MIR and collects kills.
-fn collect_kills<'tcx>(
-    body: &Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    borrow_set: &BorrowSet<'tcx>,
-) -> BTreeMap<Location, BTreeSet<BorrowIndex>> {
-    let mut collector = KillsCollector { borrow_set, tcx, body, kills: BTreeMap::default() };
-    for (block, data) in body.basic_blocks.iter_enumerated() {
-        collector.visit_basic_block_data(block, data);
-    }
-    collector.kills
-}
-
-struct KillsCollector<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    borrow_set: &'a BorrowSet<'tcx>,
-
-    /// The set of loans killed at each location.
-    kills: BTreeMap<Location, BTreeSet<BorrowIndex>>,
-}
-
-// This visitor has a similar structure to the `Borrows` dataflow computation with respect to kills,
-// and the datalog polonius fact generation for the `loan_killed_at` relation.
-impl<'tcx> KillsCollector<'_, 'tcx> {
-    /// Records the borrows on the specified place as `killed`. For example, when assigning to a
-    /// local, or on a call's return destination.
-    fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
-        // For the reasons described in graph traversal, we also filter out kills
-        // unreachable from the loan's introduction point, as they would stop traversal when
-        // e.g. checking for reachability in the subset graph through invariance constraints
-        // higher up.
-        let filter_unreachable_kills = |loan| {
-            let introduction = self.borrow_set[loan].reserve_location;
-            let reachable = introduction.is_predecessor_of(location, self.body);
-            reachable
-        };
-
-        let other_borrows_of_local = self
-            .borrow_set
-            .local_map
-            .get(&place.local)
-            .into_iter()
-            .flat_map(|bs| bs.iter())
-            .copied();
-
-        // If the borrowed place is a local with no projections, all other borrows of this
-        // local must conflict. This is purely an optimization so we don't have to call
-        // `places_conflict` for every borrow.
-        if place.projection.is_empty() {
-            if !self.body.local_decls[place.local].is_ref_to_static() {
-                self.kills
-                    .entry(location)
-                    .or_default()
-                    .extend(other_borrows_of_local.filter(|&loan| filter_unreachable_kills(loan)));
-            }
-            return;
-        }
-
-        // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
-        // pair of array indices are not equal, so that when `places_conflict` returns true, we
-        // will be assured that two places being compared definitely denotes the same sets of
-        // locations.
-        let definitely_conflicting_borrows = other_borrows_of_local
-            .filter(|&i| {
-                places_conflict(
-                    self.tcx,
-                    self.body,
-                    self.borrow_set[i].borrowed_place,
-                    place,
-                    PlaceConflictBias::NoOverlap,
-                )
-            })
-            .filter(|&loan| filter_unreachable_kills(loan));
-
-        self.kills.entry(location).or_default().extend(definitely_conflicting_borrows);
-    }
-
-    /// Records the borrows on the specified local as `killed`.
-    fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
-        if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
-            self.kills.entry(location).or_default().extend(borrow_indices.iter());
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for KillsCollector<'_, 'tcx> {
-    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
-        // Make sure there are no remaining borrows for locals that have gone out of scope.
-        if let StatementKind::StorageDead(local) = statement.kind {
-            self.record_killed_borrows_for_local(local, location);
-        }
-
-        self.super_statement(statement, location);
-    }
-
-    fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
-        // When we see `X = ...`, then kill borrows of `(*X).foo` and so forth.
-        self.record_killed_borrows_for_place(*place, location);
-        self.super_assign(place, rvalue, location);
-    }
-
-    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        // A `Call` terminator's return value can be a local which has borrows, so we need to record
-        // those as killed as well.
-        if let TerminatorKind::Call { destination, .. } = terminator.kind {
-            self.record_killed_borrows_for_place(destination, location);
-        }
-
-        self.super_terminator(terminator, location);
-    }
-}
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 142ef8ba28e..a9092b1981e 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -146,8 +146,8 @@ impl PoloniusContext {
     /// - converting NLL typeck constraints to be localized
     /// - encoding liveness constraints
     ///
-    /// Then, this graph is traversed, and combined with kills, reachability is recorded as loan
-    /// liveness, to be used by the loan scope and active loans computations.
+    /// Then, this graph is traversed, reachability is recorded as loan liveness, to be used by the
+    /// loan scope and active loans computations.
     ///
     /// The constraint data will be used to compute errors and diagnostics.
     pub(crate) fn compute_loan_liveness<'tcx>(
@@ -182,8 +182,6 @@ impl PoloniusContext {
         // Now that we have a complete graph, we can compute reachability to trace the liveness of
         // loans for the next step in the chain, the NLL loan scope and active loans computations.
         let live_loans = compute_loan_liveness(
-            tcx,
-            body,
             regioncx.liveness_constraints(),
             regioncx.outlives_constraints(),
             borrow_set,
diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
index 1289b1899eb..e4e52962bf7 100644
--- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
@@ -47,9 +47,7 @@ pub(super) fn convert_typeck_constraints<'tcx>(
                         tcx,
                         body,
                         stmt,
-                        liveness,
                         &outlives_constraint,
-                        location,
                         point,
                         universal_regions,
                     )
@@ -78,9 +76,7 @@ fn localize_statement_constraint<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     stmt: &Statement<'tcx>,
-    liveness: &LivenessValues,
     outlives_constraint: &OutlivesConstraint<'tcx>,
-    current_location: Location,
     current_point: PointIndex,
     universal_regions: &UniversalRegions<'tcx>,
 ) -> LocalizedOutlivesConstraint {
@@ -98,8 +94,8 @@ fn localize_statement_constraint<'tcx>(
             // - and that should be impossible in MIR
             //
             // When we have a more complete implementation in the future, tested with crater, etc,
-            // we can relax this to a debug assert instead, or remove it.
-            assert!(
+            // we can remove this assertion. It's a debug assert because it can be expensive.
+            debug_assert!(
                 {
                     let mut lhs_regions = FxHashSet::default();
                     tcx.for_each_free_region(lhs, |region| {
@@ -119,16 +115,8 @@ fn localize_statement_constraint<'tcx>(
                 "there should be no common regions between the LHS and RHS of an assignment"
             );
 
-            // As mentioned earlier, we should be tracking these better upstream but: we want to
-            // relate the types on entry to the type of the place on exit. That is, outlives
-            // constraints on the RHS are on entry, and outlives constraints to/from the LHS are on
-            // exit (i.e. on entry to the successor location).
             let lhs_ty = body.local_decls[lhs.local].ty;
-            let successor_location = Location {
-                block: current_location.block,
-                statement_index: current_location.statement_index + 1,
-            };
-            let successor_point = liveness.point_from_location(successor_location);
+            let successor_point = current_point;
             compute_constraint_direction(
                 tcx,
                 outlives_constraint,
@@ -195,6 +183,7 @@ fn localize_terminator_constraint<'tcx>(
         }
     }
 }
+
 /// For a given outlives constraint and CFG edge, returns the localized constraint with the
 /// appropriate `from`-`to` direction. This is computed according to whether the constraint flows to
 /// or from a free region in the given `value`, some kind of result for an effectful operation, like
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 982e640fa92..79e32dcf105 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -142,7 +142,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
             |err, self_ty, trait_id| {
                 // FIXME(const_trait_impl): Do we need any of this on the non-const codepath?
 
-                let trait_ref = TraitRef::from_method(tcx, trait_id, self.args);
+                let trait_ref = TraitRef::from_assoc(tcx, trait_id, self.args);
 
                 match self_ty.kind() {
                     Param(param_ty) => {
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index b8a65369825..a0160d1188d 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -732,7 +732,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         let tcx = *self.tcx;
 
         let trait_def_id = tcx.trait_of_assoc(def_id).unwrap();
-        let virtual_trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, virtual_instance.args);
+        let virtual_trait_ref = ty::TraitRef::from_assoc(tcx, trait_def_id, virtual_instance.args);
         let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
         let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
 
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index ae1f57c1ef6..acc21f6c6d2 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -545,7 +545,7 @@ declare_features! (
     (incomplete, inherent_associated_types, "1.52.0", Some(8995)),
     /// Allows using `pointer` and `reference` in intra-doc links
     (unstable, intra_doc_pointers, "1.51.0", Some(80896)),
-    // Allows setting the threshold for the `large_assignments` lint.
+    /// Allows setting the threshold for the `large_assignments` lint.
     (unstable, large_assignments, "1.52.0", Some(83518)),
     /// Allow to have type alias types for inter-crate use.
     (incomplete, lazy_type_alias, "1.72.0", Some(112792)),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index db56082c71a..49a4733de3b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -290,11 +290,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         debug_assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
         let trait_def_id = self.parent(def_id);
         debug_assert_matches!(self.def_kind(trait_def_id), DefKind::Trait);
-        let trait_generics = self.generics_of(trait_def_id);
-        (
-            ty::TraitRef::new_from_args(self, trait_def_id, args.truncate_to(self, trait_generics)),
-            &args[trait_generics.count()..],
-        )
+        let trait_ref = ty::TraitRef::from_assoc(self, trait_def_id, args);
+        (trait_ref, &args[trait_ref.args.len()..])
     }
 
     fn mk_args(self, args: &[Self::GenericArg]) -> ty::GenericArgsRef<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 648709e88e6..3ade3a3ef51 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -585,6 +585,9 @@ impl<'tcx> GenericArgs<'tcx> {
         tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.count())))
     }
 
+    /// Truncates this list of generic args to have at most the number of args in `generics`.
+    ///
+    /// You might be looking for [`TraitRef::from_assoc`](super::TraitRef::from_assoc).
     pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> GenericArgsRef<'tcx> {
         tcx.mk_args(&self[..generics.count()])
     }
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index c8521624ebb..fc56b006d94 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -68,7 +68,7 @@ impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> {
     }
 }
 
-#[derive_where(PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(PartialEq, Debug; I: Interner)]
 struct WipGoalEvaluation<I: Interner> {
     pub uncanonicalized_goal: Goal<I, I::Predicate>,
     pub orig_values: Vec<I::GenericArg>,
@@ -78,6 +78,8 @@ struct WipGoalEvaluation<I: Interner> {
     pub result: Option<QueryResult<I>>,
 }
 
+impl<I: Interner> Eq for WipGoalEvaluation<I> {}
+
 impl<I: Interner> WipGoalEvaluation<I> {
     fn finalize(self) -> inspect::GoalEvaluation<I> {
         inspect::GoalEvaluation {
@@ -98,7 +100,7 @@ impl<I: Interner> WipGoalEvaluation<I> {
 /// This only exists during proof tree building and does not have
 /// a corresponding struct in `inspect`. We need this to track a
 /// bunch of metadata about the current evaluation.
-#[derive_where(PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(PartialEq, Debug; I: Interner)]
 struct WipCanonicalGoalEvaluationStep<I: Interner> {
     /// Unlike `EvalCtxt::var_values`, we append a new
     /// generic arg here whenever we create a new inference
@@ -111,6 +113,8 @@ struct WipCanonicalGoalEvaluationStep<I: Interner> {
     evaluation: WipProbe<I>,
 }
 
+impl<I: Interner> Eq for WipCanonicalGoalEvaluationStep<I> {}
+
 impl<I: Interner> WipCanonicalGoalEvaluationStep<I> {
     fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> {
         let mut current = &mut self.evaluation;
@@ -132,7 +136,7 @@ impl<I: Interner> WipCanonicalGoalEvaluationStep<I> {
     }
 }
 
-#[derive_where(PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(PartialEq, Debug; I: Interner)]
 struct WipProbe<I: Interner> {
     initial_num_var_values: usize,
     steps: Vec<WipProbeStep<I>>,
@@ -140,6 +144,8 @@ struct WipProbe<I: Interner> {
     final_state: Option<inspect::CanonicalState<I, ()>>,
 }
 
+impl<I: Interner> Eq for WipProbe<I> {}
+
 impl<I: Interner> WipProbe<I> {
     fn finalize(self) -> inspect::Probe<I> {
         inspect::Probe {
@@ -150,7 +156,7 @@ impl<I: Interner> WipProbe<I> {
     }
 }
 
-#[derive_where(PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(PartialEq, Debug; I: Interner)]
 enum WipProbeStep<I: Interner> {
     AddGoal(GoalSource, inspect::CanonicalState<I, Goal<I, I::Predicate>>),
     NestedProbe(WipProbe<I>),
@@ -158,6 +164,8 @@ enum WipProbeStep<I: Interner> {
     RecordImplArgs { impl_args: inspect::CanonicalState<I, I::GenericArgs> },
 }
 
+impl<I: Interner> Eq for WipProbeStep<I> {}
+
 impl<I: Interner> WipProbeStep<I> {
     fn finalize(self) -> inspect::ProbeStep<I> {
         match self {
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 52717d73b8a..d81fa062e01 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -342,7 +342,7 @@ pub(crate) fn transform_instance<'tcx>(
         let upcast_ty = match tcx.trait_of_assoc(def_id) {
             Some(trait_id) => trait_object_ty(
                 tcx,
-                ty::Binder::dummy(ty::TraitRef::from_method(tcx, trait_id, instance.args)),
+                ty::Binder::dummy(ty::TraitRef::from_assoc(tcx, trait_id, instance.args)),
             ),
             // drop_in_place won't have a defining trait, skip the upcast
             None => instance.args.type_at(0),
@@ -481,7 +481,7 @@ fn implemented_method<'tcx>(
         trait_method = trait_method_bound;
         method_id = instance.def_id();
         trait_id = tcx.trait_of_assoc(method_id)?;
-        trait_ref = ty::EarlyBinder::bind(TraitRef::from_method(tcx, trait_id, instance.args));
+        trait_ref = ty::EarlyBinder::bind(TraitRef::from_assoc(tcx, trait_id, instance.args));
         trait_id
     } else {
         return None;
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 08315dbd21f..a9fb16b8000 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -763,7 +763,7 @@ fn instantiate_and_check_impossible_predicates<'tcx>(
     // Specifically check trait fulfillment to avoid an error when trying to resolve
     // associated items.
     if let Some(trait_def_id) = tcx.trait_of_assoc(key.0) {
-        let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, key.1);
+        let trait_ref = ty::TraitRef::from_assoc(tcx, trait_def_id, key.1);
         predicates.push(trait_ref.upcast(tcx));
     }
 
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index e6c3568620b..5c3f7d491a5 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -109,7 +109,7 @@ fn resolve_associated_item<'tcx>(
 ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
     debug!(?trait_item_id, ?typing_env, ?trait_id, ?rcvr_args, "resolve_associated_item");
 
-    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args);
+    let trait_ref = ty::TraitRef::from_assoc(tcx, trait_id, rcvr_args);
 
     let input = typing_env.as_query_input(trait_ref);
     let vtbl = match tcx.codegen_select_candidate(input) {
@@ -238,7 +238,7 @@ fn resolve_associated_item<'tcx>(
             Some(ty::Instance::new_raw(leaf_def.item.def_id, args))
         }
         traits::ImplSource::Builtin(BuiltinImplSource::Object(_), _) => {
-            let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_args);
+            let trait_ref = ty::TraitRef::from_assoc(tcx, trait_id, rcvr_args);
             if trait_ref.has_non_region_infer() || trait_ref.has_non_region_param() {
                 // We only resolve totally substituted vtable entries.
                 None
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 10d48526fd2..6591d3148cb 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -1,5 +1,3 @@
-use std::fmt::Debug;
-use std::hash::Hash;
 use std::marker::PhantomData;
 use std::ops::{ControlFlow, Deref};
 
@@ -23,18 +21,16 @@ use crate::{self as ty, Interner};
 /// 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)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, T)]
 #[derive_where(Copy; I: Interner, T: Copy)]
-#[derive_where(Hash; I: Interner, T: Hash)]
-#[derive_where(PartialEq; I: Interner, T: PartialEq)]
-#[derive_where(Eq; I: Interner, T: Eq)]
-#[derive_where(Debug; I: Interner, T: Debug)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub struct Binder<I: Interner, T> {
     value: T,
     bound_vars: I::BoundVarKinds,
 }
 
+impl<I: Interner, T: Eq> Eq for Binder<I, T> {}
+
 // FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
 // understand how to turn `T` to `T::Lifted` in the output `type Lifted`.
 impl<I: Interner, U: Interner, T> Lift<U> for Binder<I, T>
@@ -356,14 +352,9 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
 /// `instantiate`.
 ///
 /// 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)]
-#[derive_where(Eq; I: Interner, T: Eq)]
-#[derive_where(Ord; I: Interner, T: Ord)]
+#[derive_where(Clone, PartialEq, Ord, Hash, Debug; I: Interner, T)]
 #[derive_where(PartialOrd; I: Interner, T: Ord)]
-#[derive_where(Hash; I: Interner, T: Hash)]
-#[derive_where(Debug; I: Interner, T: Debug)]
+#[derive_where(Copy; I: Interner, T: Copy)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -374,6 +365,8 @@ pub struct EarlyBinder<I: Interner, T> {
     _tcx: PhantomData<fn() -> I>,
 }
 
+impl<I: Interner, T: Eq> Eq for EarlyBinder<I, T> {}
+
 /// For early binders, you should first call `instantiate` before using any visitors.
 #[cfg(feature = "nightly")]
 impl<I: Interner, T> !TypeFoldable<I> for ty::EarlyBinder<I, T> {}
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 0cb8d8902c6..de2a9186e7c 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -11,11 +11,7 @@ use crate::data_structures::HashMap;
 use crate::inherent::*;
 use crate::{self as ty, Interner, TypingMode, UniverseIndex};
 
-#[derive_where(Clone; I: Interner, V: Clone)]
-#[derive_where(Hash; I: Interner, V: Hash)]
-#[derive_where(PartialEq; I: Interner, V: PartialEq)]
-#[derive_where(Eq; I: Interner, V: Eq)]
-#[derive_where(Debug; I: Interner, V: fmt::Debug)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, V)]
 #[derive_where(Copy; I: Interner, V: Copy)]
 #[cfg_attr(
     feature = "nightly",
@@ -26,14 +22,12 @@ pub struct CanonicalQueryInput<I: Interner, V> {
     pub typing_mode: TypingMode<I>,
 }
 
+impl<I: Interner, V: Eq> Eq for CanonicalQueryInput<I, V> {}
+
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
-#[derive_where(Clone; I: Interner, V: Clone)]
-#[derive_where(Hash; I: Interner, V: Hash)]
-#[derive_where(PartialEq; I: Interner, V: PartialEq)]
-#[derive_where(Eq; I: Interner, V: Eq)]
-#[derive_where(Debug; I: Interner, V: fmt::Debug)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, V)]
 #[derive_where(Copy; I: Interner, V: Copy)]
 #[cfg_attr(
     feature = "nightly",
@@ -45,6 +39,8 @@ pub struct Canonical<I: Interner, V> {
     pub variables: I::CanonicalVarKinds,
 }
 
+impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
+
 impl<I: Interner, V> Canonical<I, V> {
     /// Allows you to map the `value` of a canonical while keeping the
     /// same set of bound variables.
@@ -89,7 +85,7 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
 /// canonical value. This is sufficient information for code to create
 /// a copy of the canonical value in some other inference context,
 /// with fresh inference variables replacing the canonical values.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
@@ -116,6 +112,8 @@ pub enum CanonicalVarKind<I: Interner> {
     PlaceholderConst(I::PlaceholderConst),
 }
 
+impl<I: Interner> Eq for CanonicalVarKind<I> {}
+
 impl<I: Interner> CanonicalVarKind<I> {
     pub fn universe(self) -> UniverseIndex {
         match self {
@@ -223,7 +221,7 @@ pub enum CanonicalTyVarKind {
 /// vectors with the original values that were replaced by canonical
 /// variables. You will need to supply it later to instantiate the
 /// canonicalized query response.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -233,6 +231,8 @@ pub struct CanonicalVarValues<I: Interner> {
     pub var_values: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for CanonicalVarValues<I> {}
+
 impl<I: Interner> CanonicalVarValues<I> {
     pub fn is_identity(&self) -> bool {
         self.var_values.iter().enumerate().all(|(bv, arg)| match arg.kind() {
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 70a8509b513..6de41b47bde 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -10,7 +10,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
 use crate::{self as ty, DebruijnIndex, Interner};
 
 /// Represents a constant in Rust.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -45,6 +45,8 @@ pub enum ConstKind<I: Interner> {
     Expr(I::ExprConst),
 }
 
+impl<I: Interner> Eq for ConstKind<I> {}
+
 impl<I: Interner> fmt::Debug for ConstKind<I> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use ConstKind::*;
@@ -63,7 +65,7 @@ impl<I: Interner> fmt::Debug for ConstKind<I> {
 }
 
 /// An unevaluated (potentially generic) constant used in the type-system.
-#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Debug, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -74,6 +76,8 @@ pub struct UnevaluatedConst<I: Interner> {
     pub args: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for UnevaluatedConst<I> {}
+
 impl<I: Interner> UnevaluatedConst<I> {
     #[inline]
     pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs
index 68b11489ae7..e8840bcfaca 100644
--- a/compiler/rustc_type_ir/src/error.rs
+++ b/compiler/rustc_type_ir/src/error.rs
@@ -18,7 +18,7 @@ impl<T> ExpectedFound<T> {
 }
 
 // Data structures used in type unification
-#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic)]
 #[cfg_attr(feature = "nightly", rustc_pass_by_value)]
 pub enum TypeError<I: Interner> {
@@ -58,6 +58,8 @@ pub enum TypeError<I: Interner> {
     TargetFeatureCast(I::DefId),
 }
 
+impl<I: Interner> Eq for TypeError<I> {}
+
 impl<I: Interner> TypeError<I> {
     pub fn involves_regions(self) -> bool {
         match self {
diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs
index c18cade0e39..d6e33f724d0 100644
--- a/compiler/rustc_type_ir/src/generic_arg.rs
+++ b/compiler/rustc_type_ir/src/generic_arg.rs
@@ -4,7 +4,7 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContex
 
 use crate::Interner;
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
@@ -15,7 +15,9 @@ pub enum GenericArgKind<I: Interner> {
     Const(I::Const),
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)]
+impl<I: Interner> Eq for GenericArgKind<I> {}
+
+#[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
@@ -24,3 +26,5 @@ pub enum TermKind<I: Interner> {
     Ty(I::Ty),
     Const(I::Const),
 }
+
+impl<I: Interner> Eq for TermKind<I> {}
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index e6462a97f8a..e39b99e992b 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -18,7 +18,7 @@ use crate::{self as ty, Interner};
 ///
 /// If neither of these functions are available, feel free to reach out to
 /// t-types for help.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -90,6 +90,8 @@ pub enum TypingMode<I: Interner> {
     PostAnalysis,
 }
 
+impl<I: Interner> Eq for TypingMode<I> {}
+
 impl<I: Interner> TypingMode<I> {
     /// Analysis outside of a body does not define any opaque types.
     pub fn non_body_analysis() -> TypingMode<I> {
diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs
index 416d355fd03..b6fb9f28930 100644
--- a/compiler/rustc_type_ir/src/opaque_ty.rs
+++ b/compiler/rustc_type_ir/src/opaque_ty.rs
@@ -6,7 +6,7 @@ use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 use crate::inherent::*;
 use crate::{self as ty, Interner};
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -17,6 +17,8 @@ pub struct OpaqueTypeKey<I: Interner> {
     pub args: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for OpaqueTypeKey<I> {}
+
 impl<I: Interner> OpaqueTypeKey<I> {
     pub fn iter_captured_args(self, cx: I) -> impl Iterator<Item = (usize, I::GenericArg)> {
         let variances = cx.variances_of(self.def_id.into());
diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs
index 7e56565917c..d757ac625f2 100644
--- a/compiler/rustc_type_ir/src/pattern.rs
+++ b/compiler/rustc_type_ir/src/pattern.rs
@@ -5,7 +5,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
 
 use crate::Interner;
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -15,3 +15,5 @@ pub enum PatternKind<I: Interner> {
     Range { start: I::Const, end: I::Const },
     Or(I::PatList),
 }
+
+impl<I: Interner> Eq for PatternKind<I> {}
diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs
index 9e4447ccd99..b53eb099c4b 100644
--- a/compiler/rustc_type_ir/src/predicate.rs
+++ b/compiler/rustc_type_ir/src/predicate.rs
@@ -15,12 +15,8 @@ use crate::visit::TypeVisitableExt as _;
 use crate::{self as ty, Interner};
 
 /// `A: 'region`
-#[derive_where(Clone; I: Interner, A: Clone)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)]
 #[derive_where(Copy; I: Interner, A: Copy)]
-#[derive_where(Hash; I: Interner, A: Hash)]
-#[derive_where(PartialEq; I: Interner, A: PartialEq)]
-#[derive_where(Eq; I: Interner, A: Eq)]
-#[derive_where(Debug; I: Interner, A: fmt::Debug)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -28,6 +24,8 @@ use crate::{self as ty, Interner};
 )]
 pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region);
 
+impl<I: Interner, A: Eq> Eq for OutlivesPredicate<I, A> {}
+
 // FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
 // understand how to turn `A` to `A::Lifted` in the output `type Lifted`.
 impl<I: Interner, U: Interner, A> Lift<U> for OutlivesPredicate<I, A>
@@ -53,7 +51,7 @@ where
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
 /// that case the `Self` parameter is absent from the generic parameters.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -67,6 +65,8 @@ pub struct TraitRef<I: Interner> {
     _use_trait_ref_new_instead: (),
 }
 
+impl<I: Interner> Eq for TraitRef<I> {}
+
 impl<I: Interner> TraitRef<I> {
     pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
         interner.debug_assert_args_compatible(trait_def_id, args);
@@ -82,7 +82,7 @@ impl<I: Interner> TraitRef<I> {
         Self::new_from_args(interner, trait_def_id, args)
     }
 
-    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
+    pub fn from_assoc(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
         let generics = interner.generics_of(trait_id);
         TraitRef::new(interner, trait_id, args.iter().take(generics.count()))
     }
@@ -128,7 +128,7 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> {
     }
 }
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -145,6 +145,8 @@ pub struct TraitPredicate<I: Interner> {
     pub polarity: PredicatePolarity,
 }
 
+impl<I: Interner> Eq for TraitPredicate<I> {}
+
 impl<I: Interner> TraitPredicate<I> {
     pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
         Self {
@@ -271,7 +273,7 @@ impl fmt::Display for PredicatePolarity {
     }
 }
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -286,6 +288,8 @@ pub enum ExistentialPredicate<I: Interner> {
     AutoTrait(I::DefId),
 }
 
+impl<I: Interner> Eq for ExistentialPredicate<I> {}
+
 impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
     /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
     /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
@@ -319,7 +323,7 @@ impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
 /// ```
 /// The generic parameters don't include the erased `Self`, only trait
 /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -333,6 +337,8 @@ pub struct ExistentialTraitRef<I: Interner> {
     _use_existential_trait_ref_new_instead: (),
 }
 
+impl<I: Interner> Eq for ExistentialTraitRef<I> {}
+
 impl<I: Interner> ExistentialTraitRef<I> {
     pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
         interner.debug_assert_existential_args_compatible(trait_def_id, args);
@@ -386,7 +392,7 @@ impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
 }
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -402,6 +408,8 @@ pub struct ExistentialProjection<I: Interner> {
     use_existential_projection_new_instead: (),
 }
 
+impl<I: Interner> Eq for ExistentialProjection<I> {}
+
 impl<I: Interner> ExistentialProjection<I> {
     pub fn new_from_args(
         interner: I,
@@ -542,7 +550,7 @@ impl From<ty::AliasTyKind> for AliasTermKind {
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
 /// * For an inherent projection, this would be `Ty::N<...>`.
 /// * For an opaque type, there is no explicit syntax.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -578,6 +586,8 @@ pub struct AliasTerm<I: Interner> {
     _use_alias_term_new_instead: (),
 }
 
+impl<I: Interner> Eq for AliasTerm<I> {}
+
 impl<I: Interner> AliasTerm<I> {
     pub fn new_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTerm<I> {
         interner.debug_assert_args_compatible(def_id, args);
@@ -752,7 +762,7 @@ impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> {
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -763,6 +773,8 @@ pub struct ProjectionPredicate<I: Interner> {
     pub term: I::Term,
 }
 
+impl<I: Interner> Eq for ProjectionPredicate<I> {}
+
 impl<I: Interner> ProjectionPredicate<I> {
     pub fn self_ty(self) -> I::Ty {
         self.projection_term.self_ty()
@@ -813,7 +825,7 @@ impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
 
 /// Used by the new solver to normalize an alias. This always expects the `term` to
 /// be an unconstrained inference variable which is used as the output.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -824,6 +836,8 @@ pub struct NormalizesTo<I: Interner> {
     pub term: I::Term,
 }
 
+impl<I: Interner> Eq for NormalizesTo<I> {}
+
 impl<I: Interner> NormalizesTo<I> {
     pub fn self_ty(self) -> I::Ty {
         self.alias.self_ty()
@@ -848,7 +862,7 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> {
     }
 }
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -859,6 +873,8 @@ pub struct HostEffectPredicate<I: Interner> {
     pub constness: BoundConstness,
 }
 
+impl<I: Interner> Eq for HostEffectPredicate<I> {}
+
 impl<I: Interner> HostEffectPredicate<I> {
     pub fn self_ty(self) -> I::Ty {
         self.trait_ref.self_ty()
@@ -892,7 +908,7 @@ impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
 /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
 /// whether the `a` type is the type that we should label as "expected" when
 /// presenting user diagnostics.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -904,8 +920,10 @@ pub struct SubtypePredicate<I: Interner> {
     pub b: I::Ty,
 }
 
+impl<I: Interner> Eq for SubtypePredicate<I> {}
+
 /// Encodes that we have to coerce *from* the `a` type to the `b` type.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -916,6 +934,8 @@ pub struct CoercePredicate<I: Interner> {
     pub b: I::Ty,
 }
 
+impl<I: Interner> Eq for CoercePredicate<I> {}
+
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
 #[cfg_attr(
     feature = "nightly",
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 8bc15ec4ff5..ff92a0070cc 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -9,7 +9,7 @@ use crate::{self as ty, Interner};
 
 /// A clause is something that can appear in where bounds or be inferred
 /// by implied bounds.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -55,7 +55,9 @@ pub enum ClauseKind<I: Interner> {
     ),
 }
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+impl<I: Interner> Eq for ClauseKind<I> {}
+
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -109,6 +111,8 @@ pub enum PredicateKind<I: Interner> {
     AliasRelate(I::Term, I::Term, AliasRelationDirection),
 }
 
+impl<I: Interner> Eq for PredicateKind<I> {}
+
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
 #[cfg_attr(
     feature = "nightly",
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 1b5d04e6025..cca81dcb4a0 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -125,7 +125,7 @@ rustc_index::newtype_index! {
 /// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))]
 pub enum RegionKind<I: Interner> {
     /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
@@ -177,6 +177,8 @@ pub enum RegionKind<I: Interner> {
     ReError(I::ErrorGuaranteed),
 }
 
+impl<I: Interner> Eq for RegionKind<I> {}
+
 impl<I: Interner> fmt::Debug for RegionKind<I> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index 3a00fe89360..223230fde9e 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -33,7 +33,7 @@ pub enum StructurallyRelateAliases {
 /// a miscompilation or unsoundness.
 ///
 /// When in doubt, use `VarianceDiagInfo::default()`
-#[derive_where(Clone, Copy, PartialEq, Eq, Debug, Default; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Debug, Default; I: Interner)]
 pub enum VarianceDiagInfo<I: Interner> {
     /// No additional information - this is the default.
     /// We will not add any additional information to error messages.
@@ -51,6 +51,8 @@ pub enum VarianceDiagInfo<I: Interner> {
     },
 }
 
+impl<I: Interner> Eq for VarianceDiagInfo<I> {}
+
 impl<I: Interner> VarianceDiagInfo<I> {
     /// Mirrors `Variance::xform` - used to 'combine' the existing
     /// and new `VarianceDiagInfo`s when our variance changes.
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index 089695d0475..afb4043648f 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -17,9 +17,6 @@
 //!
 //! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
 
-use std::fmt::Debug;
-use std::hash::Hash;
-
 use derive_where::derive_where;
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
@@ -32,25 +29,23 @@ use crate::{Canonical, CanonicalVarValues, Interner};
 /// This is only ever used as [CanonicalState]. Any type information in proof
 /// trees used mechanically has to be canonicalized as we otherwise leak
 /// inference variables from a nested `InferCtxt`.
-#[derive_where(Clone; I: Interner, T: Clone)]
+#[derive_where(Clone, PartialEq, Hash, Debug; I: Interner, T)]
 #[derive_where(Copy; I: Interner, T: Copy)]
-#[derive_where(PartialEq; I: Interner, T: PartialEq)]
-#[derive_where(Eq; I: Interner, T: Eq)]
-#[derive_where(Hash; I: Interner, T: Hash)]
-#[derive_where(Debug; I: Interner, T: Debug)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub struct State<I: Interner, T> {
     pub var_values: CanonicalVarValues<I>,
     pub data: T,
 }
 
+impl<I: Interner, T: Eq> Eq for State<I, T> {}
+
 pub type CanonicalState<I, T> = Canonical<I, State<I, T>>;
 
 /// When evaluating a goal we also store the original values
 /// for the `CanonicalVarValues` of the canonicalized goal.
 /// We use this to map any [CanonicalState] from the local `InferCtxt`
 /// of the solver query to the `InferCtxt` of the caller.
-#[derive_where(PartialEq, Eq, Hash; I: Interner)]
+#[derive_where(PartialEq, Hash; I: Interner)]
 pub struct GoalEvaluation<I: Interner> {
     pub uncanonicalized_goal: Goal<I, I::Predicate>,
     pub orig_values: Vec<I::GenericArg>,
@@ -58,7 +53,9 @@ pub struct GoalEvaluation<I: Interner> {
     pub result: QueryResult<I>,
 }
 
-#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
+impl<I: Interner> Eq for GoalEvaluation<I> {}
+
+#[derive_where(PartialEq, Hash, Debug; I: Interner)]
 pub enum GoalEvaluationKind<I: Interner> {
     Overflow,
     Evaluation {
@@ -67,10 +64,12 @@ pub enum GoalEvaluationKind<I: Interner> {
     },
 }
 
+impl<I: Interner> Eq for GoalEvaluationKind<I> {}
+
 /// A self-contained computation during trait solving. This either
 /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation
 /// of a goal.
-#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(PartialEq, Hash, Debug; I: Interner)]
 pub struct Probe<I: Interner> {
     /// What happened inside of this probe in chronological order.
     pub steps: Vec<ProbeStep<I>>,
@@ -78,7 +77,9 @@ pub struct Probe<I: Interner> {
     pub final_state: CanonicalState<I, ()>,
 }
 
-#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
+impl<I: Interner> Eq for Probe<I> {}
+
+#[derive_where(PartialEq, Hash, Debug; I: Interner)]
 pub enum ProbeStep<I: Interner> {
     /// We added a goal to the `EvalCtxt` which will get proven
     /// the next time `EvalCtxt::try_evaluate_added_goals` is called.
@@ -97,10 +98,12 @@ pub enum ProbeStep<I: Interner> {
     MakeCanonicalResponse { shallow_certainty: Certainty },
 }
 
+impl<I: Interner> Eq for ProbeStep<I> {}
+
 /// What kind of probe we're in. In case the probe represents a candidate, or
 /// the final result of the current goal - via [ProbeKind::Root] - we also
 /// store the [QueryResult].
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub enum ProbeKind<I: Interner> {
     /// The root inference context while proving a goal.
@@ -125,3 +128,5 @@ pub enum ProbeKind<I: Interner> {
     /// Checking that a rigid alias is well-formed.
     RigidAlias { result: QueryResult<I> },
 }
+
+impl<I: Interner> Eq for ProbeKind<I> {}
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index a6571ef261a..1497236039f 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -1,6 +1,5 @@
 pub mod inspect;
 
-use std::fmt;
 use std::hash::Hash;
 
 use derive_where::derive_where;
@@ -32,12 +31,8 @@ pub struct NoSolution;
 ///
 /// Most of the time the `param_env` contains the `where`-bounds of the function
 /// we're currently typechecking while the `predicate` is some trait bound.
-#[derive_where(Clone; I: Interner, P: Clone)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, P)]
 #[derive_where(Copy; I: Interner, P: Copy)]
-#[derive_where(Hash; I: Interner, P: Hash)]
-#[derive_where(PartialEq; I: Interner, P: PartialEq)]
-#[derive_where(Eq; I: Interner, P: Eq)]
-#[derive_where(Debug; I: Interner, P: fmt::Debug)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -48,6 +43,8 @@ pub struct Goal<I: Interner, P> {
     pub predicate: P,
 }
 
+impl<I: Interner, P: Eq> Eq for Goal<I, P> {}
+
 impl<I: Interner, P> Goal<I, P> {
     pub fn new(cx: I, param_env: I::ParamEnv, predicate: impl Upcast<I, P>) -> Goal<I, P> {
         Goal { param_env, predicate: predicate.upcast(cx) }
@@ -98,12 +95,8 @@ pub enum GoalSource {
     NormalizeGoal(PathKind),
 }
 
-#[derive_where(Clone; I: Interner, Goal<I, P>: Clone)]
+#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, Goal<I, P>)]
 #[derive_where(Copy; I: Interner, Goal<I, P>: Copy)]
-#[derive_where(Hash; I: Interner, Goal<I, P>: Hash)]
-#[derive_where(PartialEq; I: Interner, Goal<I, P>: PartialEq)]
-#[derive_where(Eq; I: Interner, Goal<I, P>: Eq)]
-#[derive_where(Debug; I: Interner, Goal<I, P>: fmt::Debug)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -114,8 +107,10 @@ pub struct QueryInput<I: Interner, P> {
     pub predefined_opaques_in_body: I::PredefinedOpaques,
 }
 
+impl<I: Interner, P: Eq> Eq for QueryInput<I, P> {}
+
 /// Opaques that are defined in the inference context before a query is called.
-#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)]
+#[derive_where(Clone, Hash, PartialEq, Debug, Default; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -125,8 +120,10 @@ pub struct PredefinedOpaquesData<I: Interner> {
     pub opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
 }
 
+impl<I: Interner> Eq for PredefinedOpaquesData<I> {}
+
 /// Possible ways the given goal can be proven.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 pub enum CandidateSource<I: Interner> {
     /// A user written impl.
     ///
@@ -189,6 +186,8 @@ pub enum CandidateSource<I: Interner> {
     CoherenceUnknowable,
 }
 
+impl<I: Interner> Eq for CandidateSource<I> {}
+
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
 pub enum ParamEnvSource {
     /// Preferred eagerly.
@@ -217,7 +216,7 @@ pub enum BuiltinImplSource {
     TraitUpcasting(usize),
 }
 
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub struct Response<I: Interner> {
@@ -227,8 +226,10 @@ pub struct Response<I: Interner> {
     pub external_constraints: I::ExternalConstraints,
 }
 
+impl<I: Interner> Eq for Response<I> {}
+
 /// Additional constraints returned on success.
-#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)]
+#[derive_where(Clone, Hash, PartialEq, Debug, Default; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub struct ExternalConstraintsData<I: Interner> {
@@ -237,6 +238,8 @@ pub struct ExternalConstraintsData<I: Interner> {
     pub normalization_nested_goals: NestedNormalizationGoals<I>,
 }
 
+impl<I: Interner> Eq for ExternalConstraintsData<I> {}
+
 impl<I: Interner> ExternalConstraintsData<I> {
     pub fn is_empty(&self) -> bool {
         self.region_constraints.is_empty()
@@ -245,11 +248,13 @@ impl<I: Interner> ExternalConstraintsData<I> {
     }
 }
 
-#[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)]
+#[derive_where(Clone, Hash, PartialEq, Debug, Default; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub struct NestedNormalizationGoals<I: Interner>(pub Vec<(GoalSource, Goal<I, I::Predicate>)>);
 
+impl<I: Interner> Eq for NestedNormalizationGoals<I> {}
+
 impl<I: Interner> NestedNormalizationGoals<I> {
     pub fn empty() -> Self {
         NestedNormalizationGoals(vec![])
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 73aeab5092d..bde506ffd93 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -69,7 +69,7 @@ impl AliasTyKind {
 /// Types written by the user start out as `hir::TyKind` and get
 /// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
 #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -268,6 +268,8 @@ pub enum TyKind<I: Interner> {
     Error(I::ErrorGuaranteed),
 }
 
+impl<I: Interner> Eq for TyKind<I> {}
+
 impl<I: Interner> TyKind<I> {
     pub fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
         match self {
@@ -404,7 +406,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
 /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
 /// * For an inherent projection, this would be `Ty::N<...>`.
 /// * For an opaque type, there is no explicit syntax.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 #[cfg_attr(
     feature = "nightly",
@@ -440,6 +442,8 @@ pub struct AliasTy<I: Interner> {
     pub(crate) _use_alias_ty_new_instead: (),
 }
 
+impl<I: Interner> Eq for AliasTy<I> {}
+
 impl<I: Interner> AliasTy<I> {
     pub fn new_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTy<I> {
         interner.debug_assert_args_compatible(def_id, args);
@@ -720,7 +724,7 @@ impl fmt::Debug for InferTy {
     }
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -731,7 +735,9 @@ pub struct TypeAndMut<I: Interner> {
     pub mutbl: Mutability,
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
+impl<I: Interner> Eq for TypeAndMut<I> {}
+
+#[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -748,6 +754,8 @@ pub struct FnSig<I: Interner> {
     pub abi: I::Abi,
 }
 
+impl<I: Interner> Eq for FnSig<I> {}
+
 impl<I: Interner> FnSig<I> {
     pub fn inputs(self) -> I::FnInputTys {
         self.inputs_and_output.inputs()
@@ -845,11 +853,13 @@ impl<I: Interner> fmt::Debug for FnSig<I> {
 
 // FIXME: this is a distinct type because we need to define `Encode`/`Decode`
 // impls in this crate for `Binder<I, I::Ty>`.
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 pub struct UnsafeBinderInner<I: Interner>(ty::Binder<I, I::Ty>);
 
+impl<I: Interner> Eq for UnsafeBinderInner<I> {}
+
 impl<I: Interner> From<ty::Binder<I, I::Ty>> for UnsafeBinderInner<I> {
     fn from(value: ty::Binder<I, I::Ty>) -> Self {
         UnsafeBinderInner(value)
@@ -906,7 +916,7 @@ where
 }
 
 // This is just a `FnSig` without the `FnHeader` fields.
-#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
+#[derive_where(Clone, Copy, Debug, PartialEq, Hash; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -916,6 +926,8 @@ pub struct FnSigTys<I: Interner> {
     pub inputs_and_output: I::Tys,
 }
 
+impl<I: Interner> Eq for FnSigTys<I> {}
+
 impl<I: Interner> FnSigTys<I> {
     pub fn inputs(self) -> I::FnInputTys {
         self.inputs_and_output.inputs()
@@ -958,7 +970,7 @@ impl<I: Interner> ty::Binder<I, FnSigTys<I>> {
     }
 }
 
-#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
+#[derive_where(Clone, Copy, Debug, PartialEq, Hash; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -970,7 +982,9 @@ pub struct FnHeader<I: Interner> {
     pub abi: I::Abi,
 }
 
-#[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)]
+impl<I: Interner> Eq for FnHeader<I> {}
+
+#[derive_where(Clone, Copy, Debug, PartialEq, Hash; I: Interner)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
@@ -980,3 +994,5 @@ pub struct CoroutineWitnessTypes<I: Interner> {
     pub types: I::Tys,
     pub assumptions: I::RegionAssumptions,
 }
+
+impl<I: Interner> Eq for CoroutineWitnessTypes<I> {}
diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs
index c32f8339d0b..a2e16d917a9 100644
--- a/compiler/rustc_type_ir/src/ty_kind/closure.rs
+++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs
@@ -101,7 +101,7 @@ use crate::{self as ty, Interner};
 ///   `yield` inside the coroutine.
 /// * `GR`: The "return type", which is the type of value returned upon
 ///   completion of the coroutine.
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 pub struct ClosureArgs<I: Interner> {
     /// Lifetime and type parameters from the enclosing function,
@@ -112,6 +112,8 @@ pub struct ClosureArgs<I: Interner> {
     pub args: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for ClosureArgs<I> {}
+
 /// Struct returned by `split()`.
 pub struct ClosureArgsParts<I: Interner> {
     /// This is the args of the typeck root.
@@ -203,12 +205,14 @@ impl<I: Interner> ClosureArgs<I> {
     }
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 pub struct CoroutineClosureArgs<I: Interner> {
     pub args: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for CoroutineClosureArgs<I> {}
+
 /// See docs for explanation of how each argument is used.
 ///
 /// See [`CoroutineClosureSignature`] for how these arguments are put together
@@ -348,7 +352,7 @@ impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
     }
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub struct CoroutineClosureSignature<I: Interner> {
     pub tupled_inputs_ty: I::Ty,
@@ -371,6 +375,8 @@ pub struct CoroutineClosureSignature<I: Interner> {
     pub abi: I::Abi,
 }
 
+impl<I: Interner> Eq for CoroutineClosureSignature<I> {}
+
 impl<I: Interner> CoroutineClosureSignature<I> {
     /// Construct a coroutine from the closure signature. Since a coroutine signature
     /// is agnostic to the type of generator that is returned (by-ref/by-move),
@@ -541,7 +547,7 @@ impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
     }
 }
 
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 pub struct GenSig<I: Interner> {
     pub resume_ty: I::Ty,
@@ -549,13 +555,16 @@ pub struct GenSig<I: Interner> {
     pub return_ty: I::Ty,
 }
 
+impl<I: Interner> Eq for GenSig<I> {}
 /// Similar to `ClosureArgs`; see the above documentation for more.
-#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
+#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)]
 #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
 pub struct CoroutineArgs<I: Interner> {
     pub args: I::GenericArgs,
 }
 
+impl<I: Interner> Eq for CoroutineArgs<I> {}
+
 pub struct CoroutineArgsParts<I: Interner> {
     /// This is the args of the typeck root.
     pub parent_args: I::GenericArgsSlice,
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index acbbb6df9a5..c4e599222e5 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -135,6 +135,8 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// ]);
 /// ```
 ///
+/// ## `Entry` API
+///
 /// `BTreeMap` implements an [`Entry API`], which allows for complex
 /// methods of getting, setting, updating and removing keys and their values:
 ///
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 0fb5c0bac75..9a0f5e0faef 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -373,7 +373,6 @@ impl Duration {
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_constructors_lite)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_hours(6);
@@ -381,7 +380,8 @@ impl Duration {
     /// assert_eq!(6 * 60 * 60, duration.as_secs());
     /// assert_eq!(0, duration.subsec_nanos());
     /// ```
-    #[unstable(feature = "duration_constructors_lite", issue = "140881")]
+    #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_hours(hours: u64) -> Duration {
@@ -401,7 +401,6 @@ impl Duration {
     /// # Examples
     ///
     /// ```
-    /// #![feature(duration_constructors_lite)]
     /// use std::time::Duration;
     ///
     /// let duration = Duration::from_mins(10);
@@ -409,7 +408,8 @@ impl Duration {
     /// assert_eq!(10 * 60, duration.as_secs());
     /// assert_eq!(0, duration.subsec_nanos());
     /// ```
-    #[unstable(feature = "duration_constructors_lite", issue = "140881")]
+    #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")]
     #[must_use]
     #[inline]
     pub const fn from_mins(mins: u64) -> Duration {
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 75679bbac91..0c4d49f3c99 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -36,7 +36,6 @@
 #![feature(drop_guard)]
 #![feature(duration_constants)]
 #![feature(duration_constructors)]
-#![feature(duration_constructors_lite)]
 #![feature(error_generic_member_access)]
 #![feature(exact_div)]
 #![feature(exact_size_is_empty)]
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index edbdd041145..15a7a770d1a 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -135,6 +135,8 @@ use crate::ops::Index;
 /// ]);
 /// ```
 ///
+/// ## `Entry` API
+///
 /// `HashMap` implements an [`Entry` API](#method.entry), which allows
 /// for complex methods of getting, setting, updating and removing keys and
 /// their values:
@@ -167,6 +169,8 @@ use crate::ops::Index;
 /// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);
 /// ```
 ///
+/// ## Usage with custom key types
+///
 /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
 /// We must also derive [`PartialEq`].
 ///
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 065a39a4e71..79244827059 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -421,6 +421,13 @@ impl Step for Llvm {
             ldflags.shared.push(" -latomic");
         }
 
+        if target.starts_with("arm64ec") {
+            // MSVC linker requires the -machine:arm64ec flag to be passed to
+            // know it's linking as Arm64EC (vs Arm64X).
+            ldflags.exe.push(" -machine:arm64ec");
+            ldflags.shared.push(" -machine:arm64ec");
+        }
+
         if target.is_msvc() {
             cfg.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded");
             cfg.static_crt(true);
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index e10af2b55f9..39f46bf43af 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -433,6 +433,15 @@ impl Builder<'_> {
         let out_dir = self.stage_out(compiler, mode);
         cargo.env("CARGO_TARGET_DIR", &out_dir);
 
+        // Bootstrap makes a lot of assumptions about the artifacts produced in the target
+        // directory. If users override the "build directory" using `build-dir`
+        // (https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-dir), then
+        // bootstrap couldn't find these artifacts. So we forcefully override that option to our
+        // target directory here.
+        // In the future, we could attempt to read the build-dir location from Cargo and actually
+        // respect it.
+        cargo.env("CARGO_BUILD_BUILD_DIR", &out_dir);
+
         // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
         // from out of tree it shouldn't matter, since x.py is only used for
         // building in-tree.
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 7527dff9cd8..03760faec69 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -80,11 +80,21 @@ impl CommandFingerprint {
     /// Helper method to format both Command and BootstrapCommand as a short execution line,
     /// without all the other details (e.g. environment variables).
     pub fn format_short_cmd(&self) -> String {
-        let program = Path::new(&self.program);
-        let mut line = vec![program.file_name().unwrap().to_str().unwrap().to_owned()];
-        line.extend(self.args.iter().map(|arg| arg.to_string_lossy().into_owned()));
-        line.extend(self.cwd.iter().map(|p| p.to_string_lossy().into_owned()));
-        line.join(" ")
+        use std::fmt::Write;
+
+        let mut cmd = self.program.to_string_lossy().to_string();
+        for arg in &self.args {
+            let arg = arg.to_string_lossy();
+            if arg.contains(' ') {
+                write!(cmd, " '{arg}'").unwrap();
+            } else {
+                write!(cmd, " {arg}").unwrap();
+            }
+        }
+        if let Some(cwd) = &self.cwd {
+            write!(cmd, " [workdir={}]", cwd.to_string_lossy()).unwrap();
+        }
+        cmd
     }
 }
 
@@ -434,8 +444,8 @@ impl From<Command> for BootstrapCommand {
 enum CommandStatus {
     /// The command has started and finished with some status.
     Finished(ExitStatus),
-    /// It was not even possible to start the command.
-    DidNotStart,
+    /// It was not even possible to start the command or wait for it to finish.
+    DidNotStartOrFinish,
 }
 
 /// Create a new BootstrapCommand. This is a helper function to make command creation
@@ -456,9 +466,9 @@ pub struct CommandOutput {
 
 impl CommandOutput {
     #[must_use]
-    pub fn did_not_start(stdout: OutputMode, stderr: OutputMode) -> Self {
+    pub fn not_finished(stdout: OutputMode, stderr: OutputMode) -> Self {
         Self {
-            status: CommandStatus::DidNotStart,
+            status: CommandStatus::DidNotStartOrFinish,
             stdout: match stdout {
                 OutputMode::Print => None,
                 OutputMode::Capture => Some(vec![]),
@@ -489,7 +499,7 @@ impl CommandOutput {
     pub fn is_success(&self) -> bool {
         match self.status {
             CommandStatus::Finished(status) => status.success(),
-            CommandStatus::DidNotStart => false,
+            CommandStatus::DidNotStartOrFinish => false,
         }
     }
 
@@ -501,7 +511,7 @@ impl CommandOutput {
     pub fn status(&self) -> Option<ExitStatus> {
         match self.status {
             CommandStatus::Finished(status) => Some(status),
-            CommandStatus::DidNotStart => None,
+            CommandStatus::DidNotStartOrFinish => None,
         }
     }
 
@@ -745,25 +755,11 @@ impl ExecutionContext {
         self.start(command, stdout, stderr).wait_for_output(self)
     }
 
-    fn fail(&self, message: &str, output: CommandOutput) -> ! {
-        if self.is_verbose() {
-            println!("{message}");
-        } else {
-            let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
-            // If the command captures output, the user would not see any indication that
-            // it has failed. In this case, print a more verbose error, since to provide more
-            // context.
-            if stdout.is_some() || stderr.is_some() {
-                if let Some(stdout) = output.stdout_if_present().take_if(|s| !s.trim().is_empty()) {
-                    println!("STDOUT:\n{stdout}\n");
-                }
-                if let Some(stderr) = output.stderr_if_present().take_if(|s| !s.trim().is_empty()) {
-                    println!("STDERR:\n{stderr}\n");
-                }
-                println!("Command has failed. Rerun with -v to see more details.");
-            } else {
-                println!("Command has failed. Rerun with -v to see more details.");
-            }
+    fn fail(&self, message: &str) -> ! {
+        println!("{message}");
+
+        if !self.is_verbose() {
+            println!("Command has failed. Rerun with -v to see more details.");
         }
         exit!(1);
     }
@@ -856,7 +852,7 @@ impl<'a> DeferredCommand<'a> {
                     && command.should_cache
                 {
                     exec_ctx.command_cache.insert(fingerprint.clone(), output.clone());
-                    exec_ctx.profiler.record_execution(fingerprint.clone(), start_time);
+                    exec_ctx.profiler.record_execution(fingerprint, start_time);
                 }
 
                 output
@@ -872,6 +868,8 @@ impl<'a> DeferredCommand<'a> {
         executed_at: &'a std::panic::Location<'a>,
         exec_ctx: &ExecutionContext,
     ) -> CommandOutput {
+        use std::fmt::Write;
+
         command.mark_as_executed();
 
         let process = match process.take() {
@@ -881,79 +879,82 @@ impl<'a> DeferredCommand<'a> {
 
         let created_at = command.get_created_location();
 
-        let mut message = String::new();
+        #[allow(clippy::enum_variant_names)]
+        enum FailureReason {
+            FailedAtRuntime(ExitStatus),
+            FailedToFinish(std::io::Error),
+            FailedToStart(std::io::Error),
+        }
 
-        let output = match process {
+        let (output, fail_reason) = match process {
             Ok(child) => match child.wait_with_output() {
-                Ok(result) if result.status.success() => {
+                Ok(output) if output.status.success() => {
                     // Successful execution
-                    CommandOutput::from_output(result, stdout, stderr)
+                    (CommandOutput::from_output(output, stdout, stderr), None)
                 }
-                Ok(result) => {
-                    // Command ran but failed
-                    use std::fmt::Write;
-
-                    writeln!(
-                        message,
-                        r#"
-Command {command:?} did not execute successfully.
-Expected success, got {}
-Created at: {created_at}
-Executed at: {executed_at}"#,
-                        result.status,
+                Ok(output) => {
+                    // Command started, but then it failed
+                    let status = output.status;
+                    (
+                        CommandOutput::from_output(output, stdout, stderr),
+                        Some(FailureReason::FailedAtRuntime(status)),
                     )
-                    .unwrap();
-
-                    let output = CommandOutput::from_output(result, stdout, stderr);
-
-                    if stdout.captures() {
-                        writeln!(message, "\nSTDOUT ----\n{}", output.stdout().trim()).unwrap();
-                    }
-                    if stderr.captures() {
-                        writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap();
-                    }
-
-                    output
                 }
                 Err(e) => {
                     // Failed to wait for output
-                    use std::fmt::Write;
-
-                    writeln!(
-                        message,
-                        "\n\nCommand {command:?} did not execute successfully.\
-                        \nIt was not possible to execute the command: {e:?}"
+                    (
+                        CommandOutput::not_finished(stdout, stderr),
+                        Some(FailureReason::FailedToFinish(e)),
                     )
-                    .unwrap();
-
-                    CommandOutput::did_not_start(stdout, stderr)
                 }
             },
             Err(e) => {
                 // Failed to spawn the command
-                use std::fmt::Write;
-
-                writeln!(
-                    message,
-                    "\n\nCommand {command:?} did not execute successfully.\
-                    \nIt was not possible to execute the command: {e:?}"
-                )
-                .unwrap();
-
-                CommandOutput::did_not_start(stdout, stderr)
+                (CommandOutput::not_finished(stdout, stderr), Some(FailureReason::FailedToStart(e)))
             }
         };
 
-        if !output.is_success() {
+        if let Some(fail_reason) = fail_reason {
+            let mut error_message = String::new();
+            let command_str = if exec_ctx.is_verbose() {
+                format!("{command:?}")
+            } else {
+                command.fingerprint().format_short_cmd()
+            };
+            let action = match fail_reason {
+                FailureReason::FailedAtRuntime(e) => {
+                    format!("failed with exit code {}", e.code().unwrap_or(1))
+                }
+                FailureReason::FailedToFinish(e) => {
+                    format!("failed to finish: {e:?}")
+                }
+                FailureReason::FailedToStart(e) => {
+                    format!("failed to start: {e:?}")
+                }
+            };
+            writeln!(
+                error_message,
+                r#"Command `{command_str}` {action}
+Created at: {created_at}
+Executed at: {executed_at}"#,
+            )
+            .unwrap();
+            if stdout.captures() {
+                writeln!(error_message, "\n--- STDOUT vvv\n{}", output.stdout().trim()).unwrap();
+            }
+            if stderr.captures() {
+                writeln!(error_message, "\n--- STDERR vvv\n{}", output.stderr().trim()).unwrap();
+            }
+
             match command.failure_behavior {
                 BehaviorOnFailure::DelayFail => {
                     if exec_ctx.fail_fast {
-                        exec_ctx.fail(&message, output);
+                        exec_ctx.fail(&error_message);
                     }
-                    exec_ctx.add_to_delay_failure(message);
+                    exec_ctx.add_to_delay_failure(error_message);
                 }
                 BehaviorOnFailure::Exit => {
-                    exec_ctx.fail(&message, output);
+                    exec_ctx.fail(&error_message);
                 }
                 BehaviorOnFailure::Ignore => {
                     // If failures are allowed, either the error has been printed already
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md b/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md
new file mode 100644
index 00000000000..f5be63b796c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md
@@ -0,0 +1,5 @@
+# `COLORTERM`
+
+This environment variable is used by [`-Zterminal-urls`] to detect if URLs are supported by the terminal emulator.
+
+[`-Zterminal-urls`]: ../compiler-flags/terminal-urls.html
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md b/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md
new file mode 100644
index 00000000000..46511598e70
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md
@@ -0,0 +1,11 @@
+# `QNX_TARGET`
+
+----
+
+This environment variable is mandatory when linking on `nto-qnx*_iosock` platforms. It is used to determine an `-L` path to pass to the QNX linker.
+
+You should [set this variable] by running `source qnxsdp-env.sh`.
+See [the QNX docs] for more background information.
+
+[set this variable]: https://www.qnx.com/developers/docs/qsc/com.qnx.doc.qsc.inst_larg_org/topic/build_server_developer_steps.html
+[the QNX docs]: https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.io_sock/topic/migrate_app.html.
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md
new file mode 100644
index 00000000000..be9ed02f54d
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md
@@ -0,0 +1,6 @@
+# `SDKROOT`
+
+This environment variable is used on Apple targets.
+It is passed through to the linker (currently either as `-isysroot` or `-syslibroot`).
+
+Note that this variable is not always respected. When the SDKROOT is clearly wrong (e.g. when the platform of the SDK does not match the `--target` used by rustc), this is ignored and rustc does its own detection.
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/TERM.md b/src/doc/unstable-book/src/compiler-environment-variables/TERM.md
new file mode 100644
index 00000000000..9208fd378a3
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/TERM.md
@@ -0,0 +1,5 @@
+# `TERM`
+
+This environment variable is used by [`-Zterminal-urls`] to detect if URLs are supported by the terminal emulator.
+
+[`-Zterminal-urls`]: ../compiler-flags/terminal-urls.html
diff --git a/src/doc/unstable-book/src/compiler-flags/terminal-urls.md b/src/doc/unstable-book/src/compiler-flags/terminal-urls.md
new file mode 100644
index 00000000000..a5427978f25
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/terminal-urls.md
@@ -0,0 +1,13 @@
+# `-Z terminal-urls`
+
+The tracking feature for this issue is [#125586]
+
+[#125586]: https://github.com/rust-lang/rust/issues/125586
+
+---
+
+This flag takes either a boolean or the string "auto".
+
+When enabled, use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output.
+Use "auto" to try and autodetect whether the terminal emulator supports hyperlinks.
+Currently, "auto" only enables hyperlinks if `COLORTERM=truecolor` and `TERM=xterm-256color`.
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 121f9493435..d9566c9f55c 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -19,7 +19,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 - M68k
 - CSKY
 - SPARC
-- LoongArch32
 
 ## Register classes
 
@@ -54,8 +53,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `freg`         | `f[0-31]`                          | `f`                  |
 | SPARC        | `reg`          | `r[2-29]`                          | `r`                  |
 | SPARC        | `yreg`         | `y`                                | Only clobbers        |
-| LoongArch32  | `reg`          | `$r1`, `$r[4-20]`, `$r[23,30]`     | `r`                  |
-| LoongArch32  | `freg`         | `$f[0-31]`                         | `f`                  |
 
 > **Notes**:
 > - NVPTX doesn't have a fixed register set, so named registers are not supported.
@@ -94,8 +91,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `freg`                          | None           | `f32`,                                  |
 | SPARC        | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
 | SPARC        | `yreg`                          | N/A            | Only clobbers                           |
-| LoongArch32  | `reg`                           | None           | `i8`, `i16`, `i32`, `f32`               |
-| LoongArch32  | `freg`                          | None           | `f32`, `f64`                            |
 
 ## Register aliases
 
diff --git a/src/doc/unstable-book/src/library-features/duration-constructors-lite.md b/src/doc/unstable-book/src/library-features/duration-constructors-lite.md
deleted file mode 100644
index 5238b84f776..00000000000
--- a/src/doc/unstable-book/src/library-features/duration-constructors-lite.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# `duration_constructors_lite`
-
-The tracking issue for this feature is: [#140881]
-
-[#140881]: https://github.com/rust-lang/rust/issues/140881
-
-------------------------
-
-Add the methods `from_mins`, `from_hours` to `Duration`.
-
-For `from_days` and `from_weeks` see [`duration_constructors`](https://github.com/rust-lang/rust/issues/120301).
diff --git a/src/doc/unstable-book/src/library-features/duration-constructors.md b/src/doc/unstable-book/src/library-features/duration-constructors.md
index 49ad78d1961..2626e0500b5 100644
--- a/src/doc/unstable-book/src/library-features/duration-constructors.md
+++ b/src/doc/unstable-book/src/library-features/duration-constructors.md
@@ -7,4 +7,3 @@ The tracking issue for this feature is: [#120301]
 ------------------------
 
 Add the methods `from_days` and `from_weeks` to `Duration`.
-For `from_mins` and `from_hours` see [duration-constructors-lite.md](./duration-constructors-lite.md)
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 35ace656638..73ce62cdcde 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -409,9 +409,7 @@ pub(crate) fn run_tests(
         // We ensure temp dir destructor is called.
         std::mem::drop(temp_dir);
         times.display_times();
-        // FIXME(GuillaumeGomez): Uncomment the next line once #144297 has been merged.
-        // std::process::exit(test::ERROR_EXIT_CODE);
-        std::process::exit(101);
+        std::process::exit(test::ERROR_EXIT_CODE);
     }
 }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f283a625f97..debf67e2741 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1766,7 +1766,7 @@ impl<'test> TestCx<'test> {
 
         match self.config.compare_mode {
             Some(CompareMode::Polonius) => {
-                rustc.args(&["-Zpolonius"]);
+                rustc.args(&["-Zpolonius=next"]);
             }
             Some(CompareMode::NextSolver) => {
                 rustc.args(&["-Znext-solver"]);
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index fb00b3a943f..6618ba24be6 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -9,6 +9,7 @@
 //! * All unstable lang features have tests to ensure they are actually unstable.
 //! * Language features in a group are sorted by feature name.
 
+use std::collections::BTreeSet;
 use std::collections::hash_map::{Entry, HashMap};
 use std::ffi::OsStr;
 use std::num::NonZeroU32;
@@ -21,6 +22,7 @@ use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many};
 mod tests;
 
 mod version;
+use regex::Regex;
 use version::Version;
 
 const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start";
@@ -623,3 +625,36 @@ fn map_lib_features(
         },
     );
 }
+
+fn should_document(var: &str) -> bool {
+    if var.starts_with("RUSTC_") || var.starts_with("RUST_") || var.starts_with("UNSTABLE_RUSTDOC_")
+    {
+        return true;
+    }
+    ["SDKROOT", "QNX_TARGET", "COLORTERM", "TERM"].contains(&var)
+}
+
+pub fn collect_env_vars(compiler: &Path) -> BTreeSet<String> {
+    let env_var_regex: Regex = Regex::new(r#"env::var(_os)?\("([^"]+)"#).unwrap();
+
+    let mut vars = BTreeSet::new();
+    walk(
+        compiler,
+        // skip build scripts, tests, and non-rust files
+        |path, _is_dir| {
+            filter_dirs(path)
+                || filter_not_rust(path)
+                || path.ends_with("build.rs")
+                || path.ends_with("tests.rs")
+        },
+        &mut |_entry, contents| {
+            for env_var in env_var_regex.captures_iter(contents).map(|c| c.get(2).unwrap().as_str())
+            {
+                if should_document(env_var) {
+                    vars.insert(env_var.to_owned());
+                }
+            }
+        },
+    );
+    vars
+}
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 9dc9d42d466..0ed954d48de 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -6,6 +6,8 @@ use crate::features::{CollectedFeatures, Features, Status};
 
 pub const PATH_STR: &str = "doc/unstable-book";
 
+pub const ENV_VARS_DIR: &str = "src/compiler-environment-variables";
+
 pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
 
 pub const LANG_FEATURES_DIR: &str = "src/language-features";
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index 159a1d0fa17..a7c6173d88c 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -5,11 +5,11 @@ use std::env;
 use std::fs::{self, write};
 use std::path::Path;
 
-use tidy::features::{Features, collect_lang_features, collect_lib_features};
+use tidy::features::{Features, collect_env_vars, collect_lang_features, collect_lib_features};
 use tidy::t;
 use tidy::unstable_book::{
-    LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR, collect_unstable_book_section_file_names,
-    collect_unstable_feature_names,
+    ENV_VARS_DIR, LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR,
+    collect_unstable_book_section_file_names, collect_unstable_feature_names,
 };
 
 fn generate_stub_issue(path: &Path, name: &str, issue: u32, description: &str) {
@@ -27,6 +27,11 @@ fn generate_stub_no_issue(path: &Path, name: &str, description: &str) {
     t!(write(path, content), path);
 }
 
+fn generate_stub_env_var(path: &Path, name: &str) {
+    let content = format!(include_str!("stub-env-var.md"), name = name);
+    t!(write(path, content), path);
+}
+
 fn set_to_summary_str(set: &BTreeSet<String>, dir: &str) -> String {
     set.iter()
         .map(|ref n| format!("    - [{}]({}/{}.md)", n.replace('-', "_"), dir, n))
@@ -59,7 +64,7 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur
     t!(write(&summary_path, content), summary_path);
 }
 
-fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) {
+fn generate_feature_files(src: &Path, out: &Path, features: &Features) {
     let unstable_features = collect_unstable_feature_names(features);
     let unstable_section_file_names = collect_unstable_book_section_file_names(src);
     t!(fs::create_dir_all(&out));
@@ -83,6 +88,16 @@ fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) {
     }
 }
 
+fn generate_env_files(src: &Path, out: &Path, env_vars: &BTreeSet<String>) {
+    let env_var_file_names = collect_unstable_book_section_file_names(src);
+    t!(fs::create_dir_all(&out));
+    for env_var in env_vars - &env_var_file_names {
+        let file_name = format!("{env_var}.md");
+        let out_file_path = out.join(&file_name);
+        generate_stub_env_var(&out_file_path, &env_var);
+    }
+}
+
 fn copy_recursive(from: &Path, to: &Path) {
     for entry in t!(fs::read_dir(from)) {
         let e = t!(entry);
@@ -112,21 +127,23 @@ fn main() {
         .into_iter()
         .filter(|&(ref name, _)| !lang_features.contains_key(name))
         .collect();
+    let env_vars = collect_env_vars(compiler_path);
 
     let doc_src_path = src_path.join(PATH_STR);
 
     t!(fs::create_dir_all(&dest_path));
 
-    generate_unstable_book_files(
+    generate_feature_files(
         &doc_src_path.join(LANG_FEATURES_DIR),
         &dest_path.join(LANG_FEATURES_DIR),
         &lang_features,
     );
-    generate_unstable_book_files(
+    generate_feature_files(
         &doc_src_path.join(LIB_FEATURES_DIR),
         &dest_path.join(LIB_FEATURES_DIR),
         &lib_features,
     );
+    generate_env_files(&doc_src_path.join(ENV_VARS_DIR), &dest_path.join(ENV_VARS_DIR), &env_vars);
 
     copy_recursive(&doc_src_path, &dest_path);
 
diff --git a/src/tools/unstable-book-gen/src/stub-env-var.md b/src/tools/unstable-book-gen/src/stub-env-var.md
new file mode 100644
index 00000000000..e8a7ddb855a
--- /dev/null
+++ b/src/tools/unstable-book-gen/src/stub-env-var.md
@@ -0,0 +1,9 @@
+# `{name}`
+
+Environment variables have no tracking issue. This environment variable has no documentation, and therefore is likely internal to the compiler and not meant for general use.
+
+See [the code][github search] for more information.
+
+[github search]: https://github.com/search?q=repo%3Arust-lang%2Frust+%22{name}%22+path%3Acompiler&type=code
+
+------------------------
diff --git a/tests/assembly-llvm/asm/loongarch-type.rs b/tests/assembly-llvm/asm/loongarch-type.rs
index c782be19f1d..95d811a6bd0 100644
--- a/tests/assembly-llvm/asm/loongarch-type.rs
+++ b/tests/assembly-llvm/asm/loongarch-type.rs
@@ -1,8 +1,15 @@
 //@ add-core-stubs
+//@ revisions: loongarch32 loongarch64
+
 //@ assembly-output: emit-asm
-//@ compile-flags: --target loongarch64-unknown-linux-gnu
+
+//@[loongarch32] compile-flags: --target loongarch32-unknown-none
+//@[loongarch32] needs-llvm-components: loongarch
+
+//@[loongarch64] compile-flags: --target loongarch64-unknown-none
+//@[loongarch64] needs-llvm-components: loongarch
+
 //@ compile-flags: -Zmerge-functions=disabled
-//@ needs-llvm-components: loongarch
 
 #![feature(no_core, f16)]
 #![crate_type = "rlib"]
@@ -22,7 +29,7 @@ extern "C" {
 // CHECK-LABEL: sym_fn:
 // CHECK: #APP
 // CHECK: pcalau12i $t0, %got_pc_hi20(extern_func)
-// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_func)
+// CHECK: ld.{{[wd]}} $t0, $t0, %got_pc_lo12(extern_func)
 // CHECK: #NO_APP
 #[no_mangle]
 pub unsafe fn sym_fn() {
@@ -32,7 +39,7 @@ pub unsafe fn sym_fn() {
 // CHECK-LABEL: sym_static:
 // CHECK: #APP
 // CHECK: pcalau12i $t0, %got_pc_hi20(extern_static)
-// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_static)
+// CHECK: ld.{{[wd]}} $t0, $t0, %got_pc_lo12(extern_static)
 // CHECK: #NO_APP
 #[no_mangle]
 pub unsafe fn sym_static() {
@@ -87,16 +94,18 @@ check!(reg_i32, i32, reg, "move");
 // CHECK: #NO_APP
 check!(reg_f32, f32, reg, "move");
 
-// CHECK-LABEL: reg_i64:
-// CHECK: #APP
-// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
-// CHECK: #NO_APP
+// loongarch64-LABEL: reg_i64:
+// loongarch64: #APP
+// loongarch64: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check!(reg_i64, i64, reg, "move");
 
-// CHECK-LABEL: reg_f64:
-// CHECK: #APP
-// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
-// CHECK: #NO_APP
+// loongarch64-LABEL: reg_f64:
+// loongarch64: #APP
+// loongarch64: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check!(reg_f64, f64, reg, "move");
 
 // CHECK-LABEL: reg_ptr:
@@ -153,16 +162,18 @@ check_reg!(r4_i32, i32, "$r4", "move");
 // CHECK: #NO_APP
 check_reg!(r4_f32, f32, "$r4", "move");
 
-// CHECK-LABEL: r4_i64:
-// CHECK: #APP
-// CHECK: move $a0, $a0
-// CHECK: #NO_APP
+// loongarch64-LABEL: r4_i64:
+// loongarch64: #APP
+// loongarch64: move $a0, $a0
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check_reg!(r4_i64, i64, "$r4", "move");
 
-// CHECK-LABEL: r4_f64:
-// CHECK: #APP
-// CHECK: move $a0, $a0
-// CHECK: #NO_APP
+// loongarch64-LABEL: r4_f64:
+// loongarch64: #APP
+// loongarch64: move $a0, $a0
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check_reg!(r4_f64, f64, "$r4", "move");
 
 // CHECK-LABEL: r4_ptr:
diff --git a/tests/crashes/135646.rs b/tests/crashes/135646.rs
deleted file mode 100644
index 841ea5b81b4..00000000000
--- a/tests/crashes/135646.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: #135646
-//@ compile-flags: -Zpolonius=next
-//@ edition: 2024
-
-fn main() {
-    &{ [1, 2, 3][4] };
-}
diff --git a/tests/run-make/raw-dylib-link-ordinal/exporter.def b/tests/run-make/raw-dylib-link-ordinal/exporter.def
index 5d87c580a54..0544e9f1803 100644
--- a/tests/run-make/raw-dylib-link-ordinal/exporter.def
+++ b/tests/run-make/raw-dylib-link-ordinal/exporter.def
@@ -1,5 +1,5 @@
 LIBRARY exporter
 EXPORTS
     exported_function @13 NONAME
-    exported_variable @5 NONAME
+    exported_variable @5 NONAME DATA
     print_exported_variable @9 NONAME
diff --git a/tests/run-make/raw-dylib-link-ordinal/rmake.rs b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
index 43274b9765b..b9254b16753 100644
--- a/tests/run-make/raw-dylib-link-ordinal/rmake.rs
+++ b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
@@ -11,7 +11,7 @@
 
 //@ only-windows
 
-use run_make_support::{cc, diff, is_windows_msvc, run, rustc};
+use run_make_support::{cc, diff, extra_c_flags, is_windows_msvc, run, rustc};
 
 // NOTE: build_native_dynamic lib is not used, as the special `def` files
 // must be passed to the CC compiler.
@@ -24,6 +24,7 @@ fn main() {
         cc().input("exporter.obj")
             .arg("exporter.def")
             .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
+            .args(extra_c_flags())
             .run();
     } else {
         cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
new file mode 100644
index 00000000000..8742d4bd82c
--- /dev/null
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
@@ -0,0 +1,38 @@
+error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:27:18
+   |
+LL |         asm!("", out("$r0") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$tp`: reserved for TLS
+  --> $DIR/bad-reg.rs:29:18
+   |
+LL |         asm!("", out("$tp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:31:18
+   |
+LL |         asm!("", out("$sp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r21`: reserved by the ABI
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("$r21") _);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:35:18
+   |
+LL |         asm!("", out("$fp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:37:18
+   |
+LL |         asm!("", out("$r31") _);
+   |                  ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
new file mode 100644
index 00000000000..e6cb6e40c70
--- /dev/null
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
@@ -0,0 +1,62 @@
+error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:27:18
+   |
+LL |         asm!("", out("$r0") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$tp`: reserved for TLS
+  --> $DIR/bad-reg.rs:29:18
+   |
+LL |         asm!("", out("$tp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:31:18
+   |
+LL |         asm!("", out("$sp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r21`: reserved by the ABI
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("$r21") _);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:35:18
+   |
+LL |         asm!("", out("$fp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:37:18
+   |
+LL |         asm!("", out("$r31") _);
+   |                  ^^^^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:41:26
+   |
+LL |         asm!("/* {} */", in(freg) f);
+   |                          ^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:43:26
+   |
+LL |         asm!("/* {} */", out(freg) _);
+   |                          ^^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:45:26
+   |
+LL |         asm!("/* {} */", in(freg) d);
+   |                          ^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:47:26
+   |
+LL |         asm!("/* {} */", out(freg) d);
+   |                          ^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
index 0e544119650..8742d4bd82c 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
@@ -1,35 +1,35 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:22:18
+  --> $DIR/bad-reg.rs:27:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:24:18
+  --> $DIR/bad-reg.rs:29:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:26:18
+  --> $DIR/bad-reg.rs:31:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:28:18
+  --> $DIR/bad-reg.rs:33:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:30:18
+  --> $DIR/bad-reg.rs:35:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:37:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
index 6d0410dc6a1..e6cb6e40c70 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
@@ -1,59 +1,59 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:22:18
+  --> $DIR/bad-reg.rs:27:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:24:18
+  --> $DIR/bad-reg.rs:29:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:26:18
+  --> $DIR/bad-reg.rs:31:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:28:18
+  --> $DIR/bad-reg.rs:33:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:30:18
+  --> $DIR/bad-reg.rs:35:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:37:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:36:26
+  --> $DIR/bad-reg.rs:41:26
    |
 LL |         asm!("/* {} */", in(freg) f);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:38:26
+  --> $DIR/bad-reg.rs:43:26
    |
 LL |         asm!("/* {} */", out(freg) _);
    |                          ^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:40:26
+  --> $DIR/bad-reg.rs:45:26
    |
 LL |         asm!("/* {} */", in(freg) d);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:42:26
+  --> $DIR/bad-reg.rs:47:26
    |
 LL |         asm!("/* {} */", out(freg) d);
    |                          ^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs
index 685b460bc92..0d3eba07f14 100644
--- a/tests/ui/asm/loongarch/bad-reg.rs
+++ b/tests/ui/asm/loongarch/bad-reg.rs
@@ -1,6 +1,11 @@
 //@ add-core-stubs
 //@ needs-asm-support
-//@ revisions: loongarch64_lp64d loongarch64_lp64s
+//@ revisions: loongarch32_ilp32d loongarch32_ilp32s loongarch64_lp64d loongarch64_lp64s
+//@ min-llvm-version: 20
+//@[loongarch32_ilp32d] compile-flags: --target loongarch32-unknown-none
+//@[loongarch32_ilp32d] needs-llvm-components: loongarch
+//@[loongarch32_ilp32s] compile-flags: --target loongarch32-unknown-none-softfloat
+//@[loongarch32_ilp32s] needs-llvm-components: loongarch
 //@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu
 //@[loongarch64_lp64d] needs-llvm-components: loongarch
 //@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat
@@ -34,12 +39,12 @@ fn f() {
 
         asm!("", out("$f0") _); // ok
         asm!("/* {} */", in(freg) f);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", out(freg) _);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", in(freg) d);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", out(freg) d);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
     }
 }
diff --git a/tests/ui/issues/issue-15783.rs b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs
index ef948a1a88c..3322ed71c60 100644
--- a/tests/ui/issues/issue-15783.rs
+++ b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15783
+
 //@ dont-require-annotations: NOTE
 
 pub fn foo(params: Option<&[&str]>) -> usize {
diff --git a/tests/ui/issues/issue-15783.stderr b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr
index c9c9a723a86..050eb4baa41 100644
--- a/tests/ui/issues/issue-15783.stderr
+++ b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-15783.rs:10:19
+  --> $DIR/array-slice-coercion-mismatch-15783.rs:12:19
    |
 LL |     let msg = foo(x);
    |               --- ^ expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
@@ -9,7 +9,7 @@ LL |     let msg = foo(x);
    = note: expected enum `Option<&[&str]>`
               found enum `Option<&[&str; 1]>`
 note: function defined here
-  --> $DIR/issue-15783.rs:3:8
+  --> $DIR/array-slice-coercion-mismatch-15783.rs:5:8
    |
 LL | pub fn foo(params: Option<&[&str]>) -> usize {
    |        ^^^ -----------------------
diff --git a/tests/ui/issues/issue-16256.rs b/tests/ui/closures/unused-closure-ice-16256.rs
index 1024e4511d6..fd569dd8a0a 100644
--- a/tests/ui/issues/issue-16256.rs
+++ b/tests/ui/closures/unused-closure-ice-16256.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16256
+
 //@ run-pass
 
 fn main() {
diff --git a/tests/ui/issues/issue-16256.stderr b/tests/ui/closures/unused-closure-ice-16256.stderr
index 75c3ec1bd1c..9df433add5d 100644
--- a/tests/ui/issues/issue-16256.stderr
+++ b/tests/ui/closures/unused-closure-ice-16256.stderr
@@ -1,5 +1,5 @@
 warning: unused closure that must be used
-  --> $DIR/issue-16256.rs:5:5
+  --> $DIR/unused-closure-ice-16256.rs:7:5
    |
 LL |     |c: u8| buf.push(c);
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-15793.rs b/tests/ui/codegen/nested-enum-match-optimization-15793.rs
index af92e9dfa4c..420e3ad82b2 100644
--- a/tests/ui/issues/issue-15793.rs
+++ b/tests/ui/codegen/nested-enum-match-optimization-15793.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15793
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/issues/issue-15523-big.rs b/tests/ui/derives/derive-partial-ord-discriminant-64bit.rs
index 7214a4fb1d5..5b6bf6fbf1f 100644
--- a/tests/ui/issues/issue-15523-big.rs
+++ b/tests/ui/derives/derive-partial-ord-discriminant-64bit.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15523
+
 //@ run-pass
 // Issue 15523: derive(PartialOrd) should use the provided
 // discriminant values for the derived ordering.
@@ -28,7 +30,6 @@ fn main() {
     assert!(Eu64::Pos2 < Eu64::PosMax);
     assert!(Eu64::Pos1 < Eu64::PosMax);
 
-
     assert!(Ei64::Pos2 > Ei64::Pos1);
     assert!(Ei64::Pos2 > Ei64::Neg1);
     assert!(Ei64::Pos1 > Ei64::Neg1);
diff --git a/tests/ui/issues/issue-15523.rs b/tests/ui/derives/derive-partial-ord-discriminant.rs
index 9fc2e51c6ab..28f325ec966 100644
--- a/tests/ui/issues/issue-15523.rs
+++ b/tests/ui/derives/derive-partial-ord-discriminant.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15523
+
 //@ run-pass
 // Issue 15523: derive(PartialOrd) should use the provided
 // discriminant values for the derived ordering.
diff --git a/tests/ui/drop/dropck-normalize-errors.stderr b/tests/ui/drop/dropck-normalize-errors.nll.stderr
index 2bb5909c6b2..b008daa51a3 100644
--- a/tests/ui/drop/dropck-normalize-errors.stderr
+++ b/tests/ui/drop/dropck-normalize-errors.nll.stderr
@@ -1,44 +1,44 @@
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `ADecoder<'a>`
-  --> $DIR/dropck-normalize-errors.rs:15:28
+  --> $DIR/dropck-normalize-errors.rs:19:28
    |
 LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
    |                            ^^^^^^^^^^^^ within `ADecoder<'a>`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:26:12
+  --> $DIR/dropck-normalize-errors.rs:30:12
    |
 LL | pub struct BDecoder {
    |            ^^^^^^^^
 note: required because it appears within the type `ADecoder<'a>`
-  --> $DIR/dropck-normalize-errors.rs:12:12
+  --> $DIR/dropck-normalize-errors.rs:16:12
    |
 LL | pub struct ADecoder<'a> {
    |            ^^^^^^^^
    = note: the return type of a function must have a statically known size
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:23:20
+  --> $DIR/dropck-normalize-errors.rs:27:20
    |
 LL |     type Decoder = BDecoder;
    |                    ^^^^^^^^ within `BDecoder`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:26:12
+  --> $DIR/dropck-normalize-errors.rs:30:12
    |
 LL | pub struct BDecoder {
    |            ^^^^^^^^
 note: required by a bound in `Decode::Decoder`
-  --> $DIR/dropck-normalize-errors.rs:4:5
+  --> $DIR/dropck-normalize-errors.rs:8:5
    |
 LL |     type Decoder;
    |     ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder`
@@ -48,25 +48,25 @@ LL |     type Decoder: ?Sized;
    |                 ++++++++
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
-  --> $DIR/dropck-normalize-errors.rs:27:22
+  --> $DIR/dropck-normalize-errors.rs:31:22
    |
 LL |     non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
-  --> $DIR/dropck-normalize-errors.rs:15:28
+  --> $DIR/dropck-normalize-errors.rs:19:28
    |
 LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
    |                            ^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/drop/dropck-normalize-errors.polonius.stderr b/tests/ui/drop/dropck-normalize-errors.polonius.stderr
new file mode 100644
index 00000000000..f8674b8e34a
--- /dev/null
+++ b/tests/ui/drop/dropck-normalize-errors.polonius.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:19:28
+   |
+LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
+   |                            ^^^^^^^^^^^^ within `ADecoder<'a>`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:30:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required because it appears within the type `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:16:12
+   |
+LL | pub struct ADecoder<'a> {
+   |            ^^^^^^^^
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:27:20
+   |
+LL |     type Decoder = BDecoder;
+   |                    ^^^^^^^^ within `BDecoder`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:30:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required by a bound in `Decode::Decoder`
+  --> $DIR/dropck-normalize-errors.rs:8:5
+   |
+LL |     type Decoder;
+   |     ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Decoder: ?Sized;
+   |                 ++++++++
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
+  --> $DIR/dropck-normalize-errors.rs:31:22
+   |
+LL |     non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/drop/dropck-normalize-errors.rs b/tests/ui/drop/dropck-normalize-errors.rs
index 793122bd33d..2ade63f27c5 100644
--- a/tests/ui/drop/dropck-normalize-errors.rs
+++ b/tests/ui/drop/dropck-normalize-errors.rs
@@ -1,5 +1,9 @@
 // Test that we don't ICE when computing the drop types for
 
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius
+//@ [polonius] compile-flags: -Zpolonius=next
+
 trait Decode<'a> {
     type Decoder;
 }
@@ -14,7 +18,7 @@ pub struct ADecoder<'a> {
 }
 fn make_a_decoder<'a>() -> ADecoder<'a> {
     //~^ ERROR the trait bound
-    //~| ERROR the trait bound
+    //[nll]~| ERROR the trait bound
     panic!()
 }
 
diff --git a/tests/ui/issues/issue-15063.rs b/tests/ui/drop/enum-drop-impl-15063.rs
index 969dbe5fad2..a8198abafa0 100644
--- a/tests/ui/issues/issue-15063.rs
+++ b/tests/ui/drop/enum-drop-impl-15063.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15063
+
 //@ run-pass
 #![allow(dead_code)]
 #![allow(unused_variables)]
diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/drop/generic-drop-trait-bound-15858.rs
index 27887d49e3e..682604d17d8 100644
--- a/tests/ui/issues/issue-15858.rs
+++ b/tests/ui/drop/generic-drop-trait-bound-15858.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15858
+
 //@ run-pass
 // FIXME(static_mut_refs): this could use an atomic
 #![allow(static_mut_refs)]
diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/drop/generic-drop-trait-bound-15858.stderr
index 0c082cc0862..86cd6cb6026 100644
--- a/tests/ui/issues/issue-15858.stderr
+++ b/tests/ui/drop/generic-drop-trait-bound-15858.stderr
@@ -1,5 +1,5 @@
 warning: method `do_something` is never used
-  --> $DIR/issue-15858.rs:7:8
+  --> $DIR/generic-drop-trait-bound-15858.rs:9:8
    |
 LL | trait Bar {
    |       --- method in this trait
diff --git a/tests/ui/issues/issue-15763.rs b/tests/ui/drop/nested-return-drop-order.rs
index 0ebadd80541..67ab52e6250 100644
--- a/tests/ui/issues/issue-15763.rs
+++ b/tests/ui/drop/nested-return-drop-order.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15763
+
 //@ run-pass
 #![allow(unreachable_code)]
 
diff --git a/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs b/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs
new file mode 100644
index 00000000000..ecc862ec7be
--- /dev/null
+++ b/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs
@@ -0,0 +1,34 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16151
+
+//@ run-pass
+
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
+use std::mem;
+
+static mut DROP_COUNT: usize = 0;
+
+struct Fragment;
+
+impl Drop for Fragment {
+    fn drop(&mut self) {
+        unsafe {
+            DROP_COUNT += 1;
+        }
+    }
+}
+
+fn main() {
+    {
+        let mut fragments = vec![Fragment, Fragment, Fragment];
+        let _new_fragments: Vec<Fragment> = mem::replace(&mut fragments, vec![])
+            .into_iter()
+            .skip_while(|_fragment| {
+                true
+            }).collect();
+    }
+    unsafe {
+        assert_eq!(DROP_COUNT, 3);
+    }
+}
diff --git a/tests/ui/issues/issue-16492.rs b/tests/ui/drop/struct-field-drop-order.rs
index cfdba5fda35..80e3ea616a5 100644
--- a/tests/ui/issues/issue-16492.rs
+++ b/tests/ui/drop/struct-field-drop-order.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16492
+
 //@ run-pass
 #![allow(non_snake_case)]
 
diff --git a/tests/ui/issues/issue-16441.rs b/tests/ui/extern/empty-struct-extern-fn-16441.rs
index 58cfb389297..82f2eee611d 100644
--- a/tests/ui/issues/issue-16441.rs
+++ b/tests/ui/extern/empty-struct-extern-fn-16441.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16441
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/issues/issue-15094.rs b/tests/ui/fn/fn-traits-call-once-signature-15094.rs
index 408ab82eb8c..f550bafe43d 100644
--- a/tests/ui/issues/issue-15094.rs
+++ b/tests/ui/fn/fn-traits-call-once-signature-15094.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15094
+
 #![feature(fn_traits, unboxed_closures)]
 
 use std::{fmt, ops};
diff --git a/tests/ui/issues/issue-15094.stderr b/tests/ui/fn/fn-traits-call-once-signature-15094.stderr
index 8e0fc8f1770..bb1d336e848 100644
--- a/tests/ui/issues/issue-15094.stderr
+++ b/tests/ui/fn/fn-traits-call-once-signature-15094.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `call_once` has an incompatible type for trait
-  --> $DIR/issue-15094.rs:11:5
+  --> $DIR/fn-traits-call-once-signature-15094.rs:13:5
    |
 LL |     fn call_once(self, _args: ()) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn
diff --git a/tests/ui/issues/issue-15774.rs b/tests/ui/imports/enum-variant-import-path-15774.rs
index dadd59cc077..583fe4da179 100644
--- a/tests/ui/issues/issue-15774.rs
+++ b/tests/ui/imports/enum-variant-import-path-15774.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15774
+
 //@ edition: 2015
 //@ run-pass
 
diff --git a/tests/ui/inference/iterator-sum-array-15673.rs b/tests/ui/inference/iterator-sum-array-15673.rs
new file mode 100644
index 00000000000..c3d94415aff
--- /dev/null
+++ b/tests/ui/inference/iterator-sum-array-15673.rs
@@ -0,0 +1,11 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15673
+
+//@ run-pass
+#![allow(stable_features)]
+
+#![feature(iter_arith)]
+
+fn main() {
+    let x: [u64; 3] = [1, 2, 3];
+    assert_eq!(6, (0..3).map(|i| x[i]).sum::<u64>());
+}
diff --git a/tests/ui/issues/issue-15965.rs b/tests/ui/inference/return-block-type-inference-15965.rs
index eef4900d432..50753e309e8 100644
--- a/tests/ui/issues/issue-15965.rs
+++ b/tests/ui/inference/return-block-type-inference-15965.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15965
+
 fn main() {
     return
         { return () }
diff --git a/tests/ui/issues/issue-15965.stderr b/tests/ui/inference/return-block-type-inference-15965.stderr
index 14727e74334..fc4f2defe7f 100644
--- a/tests/ui/issues/issue-15965.stderr
+++ b/tests/ui/inference/return-block-type-inference-15965.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/issue-15965.rs:3:9
+  --> $DIR/return-block-type-inference-15965.rs:5:9
    |
 LL | /         { return () }
 LL | |
diff --git a/tests/ui/issues/issue-15756.rs b/tests/ui/iterators/explicit-deref-non-deref-type-15756.rs
index e0861dee61e..6d4a3bffcf7 100644
--- a/tests/ui/issues/issue-15756.rs
+++ b/tests/ui/iterators/explicit-deref-non-deref-type-15756.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15756
+
 use std::slice::Chunks;
 use std::slice::ChunksMut;
 
diff --git a/tests/ui/issues/issue-15756.stderr b/tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr
index a487d360bef..b4f9aab8496 100644
--- a/tests/ui/issues/issue-15756.stderr
+++ b/tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[T]` cannot be known at compilation time
-  --> $DIR/issue-15756.rs:7:10
+  --> $DIR/explicit-deref-non-deref-type-15756.rs:9:10
    |
 LL |     &mut something
    |          ^^^^^^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/issues/issue-15034.rs b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs
index 9ea6ed89ca2..e7f9a94231f 100644
--- a/tests/ui/issues/issue-15034.rs
+++ b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15034
+
 pub struct Lexer<'a> {
     input: &'a str,
 }
diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr
index 7db8ade2e48..0762714d259 100644
--- a/tests/ui/issues/issue-15034.stderr
+++ b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr
@@ -1,5 +1,5 @@
 error[E0621]: explicit lifetime required in the type of `lexer`
-  --> $DIR/issue-15034.rs:17:9
+  --> $DIR/nondeterministic-lifetime-errors-15034.rs:19:9
    |
 LL |         Parser { lexer: lexer }
    |         ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
diff --git a/tests/ui/lifetimes/struct-lifetime-inference-15735.rs b/tests/ui/lifetimes/struct-lifetime-inference-15735.rs
new file mode 100644
index 00000000000..39e619648eb
--- /dev/null
+++ b/tests/ui/lifetimes/struct-lifetime-inference-15735.rs
@@ -0,0 +1,19 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15735
+
+//@ check-pass
+#![allow(dead_code)]
+struct A<'a> {
+    a: &'a i32,
+    b: &'a i32,
+}
+
+impl <'a> A<'a> {
+    fn foo<'b>(&'b self) {
+        A {
+            a: self.a,
+            b: self.b,
+        };
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/issues/issue-15189.rs b/tests/ui/macros/for-loop-macro-rules-hygiene.rs
index 4dbe2179dd9..fcebda1b9da 100644
--- a/tests/ui/issues/issue-15189.rs
+++ b/tests/ui/macros/for-loop-macro-rules-hygiene.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15189
+
 //@ run-pass
 macro_rules! third {
     ($e:expr) => ({let x = 2; $e[x]})
diff --git a/tests/ui/issues/issue-15167.rs b/tests/ui/macros/macro-hygiene-scope-15167.rs
index a2653c10ea4..6578f898a5f 100644
--- a/tests/ui/issues/issue-15167.rs
+++ b/tests/ui/macros/macro-hygiene-scope-15167.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15167
+
 // macro f should not be able to inject a reference to 'n'.
 
 macro_rules! f { () => (n) }
diff --git a/tests/ui/issues/issue-15167.stderr b/tests/ui/macros/macro-hygiene-scope-15167.stderr
index 53082ea0ec6..58112c52df1 100644
--- a/tests/ui/issues/issue-15167.stderr
+++ b/tests/ui/macros/macro-hygiene-scope-15167.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -10,7 +10,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -21,7 +21,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -32,7 +32,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
diff --git a/tests/ui/issues/issue-15571.rs b/tests/ui/moves/match-move-same-binding-15571.rs
index cf17113a282..f6d79c6d76c 100644
--- a/tests/ui/issues/issue-15571.rs
+++ b/tests/ui/moves/match-move-same-binding-15571.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15571
+
 //@ run-pass
 
 fn match_on_local() {
diff --git a/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.rs b/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.rs
new file mode 100644
index 00000000000..0fb0cee2013
--- /dev/null
+++ b/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.rs
@@ -0,0 +1,13 @@
+//! Regression test for #145164: For normal calls, make sure the suggestion to borrow generic inputs
+//! uses the generic args from the callee's type rather than those attached to the callee's HIR
+//! node. In cases where the callee isn't an identifier expression, its HIR node won't have its
+//! generic arguments attached, which could lead to ICE when it had other generic args. In this
+//! case, the callee expression is `run.clone()`, to which `clone`'s generic arguments are attached.
+
+fn main() {
+    let value = String::new();
+    run.clone()(value, ());
+    run(value, ());
+    //~^ ERROR use of moved value: `value`
+}
+fn run<F, T: Clone>(value: T, f: F) {}
diff --git a/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.stderr b/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.stderr
new file mode 100644
index 00000000000..8c29bfbd290
--- /dev/null
+++ b/tests/ui/moves/use-correct-generic-args-in-borrow-suggest.stderr
@@ -0,0 +1,18 @@
+error[E0382]: use of moved value: `value`
+  --> $DIR/use-correct-generic-args-in-borrow-suggest.rs:10:9
+   |
+LL |     let value = String::new();
+   |         ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
+LL |     run.clone()(value, ());
+   |                 ----- value moved here
+LL |     run(value, ());
+   |         ^^^^^ value used here after move
+   |
+help: consider borrowing `value`
+   |
+LL |     run.clone()(&value, ());
+   |                 +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/issues/issue-15207.rs b/tests/ui/never/never-type-method-call-15207.rs
index 356e55ac912..69cdeeabb7c 100644
--- a/tests/ui/issues/issue-15207.rs
+++ b/tests/ui/never/never-type-method-call-15207.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15207
+
 fn main() {
     loop {
         break.push(1) //~ ERROR no method named `push` found for type `!`
diff --git a/tests/ui/issues/issue-15207.stderr b/tests/ui/never/never-type-method-call-15207.stderr
index a1047e27ba2..265e7c8611d 100644
--- a/tests/ui/issues/issue-15207.stderr
+++ b/tests/ui/never/never-type-method-call-15207.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `push` found for type `!` in the current scope
-  --> $DIR/issue-15207.rs:3:15
+  --> $DIR/never-type-method-call-15207.rs:5:15
    |
 LL |         break.push(1)
    |               ^^^^ method not found in `!`
diff --git a/tests/ui/nll/issue-46589.nll.stderr b/tests/ui/nll/issue-46589.nll.stderr
index dc80c1d08de..f2d08d1f4c8 100644
--- a/tests/ui/nll/issue-46589.nll.stderr
+++ b/tests/ui/nll/issue-46589.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `**other` as mutable more than once at a time
-  --> $DIR/issue-46589.rs:24:21
+  --> $DIR/issue-46589.rs:25:21
    |
 LL |         *other = match (*other).get_self() {
    |                        -------- first mutable borrow occurs here
diff --git a/tests/ui/nll/issue-46589.polonius.stderr b/tests/ui/nll/issue-46589.polonius.stderr
new file mode 100644
index 00000000000..f2d08d1f4c8
--- /dev/null
+++ b/tests/ui/nll/issue-46589.polonius.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `**other` as mutable more than once at a time
+  --> $DIR/issue-46589.rs:25:21
+   |
+LL |         *other = match (*other).get_self() {
+   |                        -------- first mutable borrow occurs here
+LL |             Some(s) => s,
+LL |             None => (*other).new_self()
+   |                     ^^^^^^^^
+   |                     |
+   |                     second mutable borrow occurs here
+   |                     first borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/issue-46589.rs b/tests/ui/nll/issue-46589.rs
index 10aff0d7b4e..9a23f61b8cb 100644
--- a/tests/ui/nll/issue-46589.rs
+++ b/tests/ui/nll/issue-46589.rs
@@ -1,9 +1,10 @@
 //@ ignore-compare-mode-polonius (explicit revisions)
-//@ revisions: nll polonius_next polonius
-//@ [polonius_next] check-pass
-//@ [polonius_next] compile-flags: -Zpolonius=next
-//@ [polonius] check-pass
-//@ [polonius] compile-flags: -Zpolonius
+//@ revisions: nll polonius legacy
+//@ [nll] known-bug: #46589
+//@ [polonius] known-bug: #46589
+//@ [polonius] compile-flags: -Zpolonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Zpolonius=legacy
 
 struct Foo;
 
@@ -22,7 +23,6 @@ impl Foo {
         *other = match (*other).get_self() {
             Some(s) => s,
             None => (*other).new_self()
-            //[nll]~^ ERROR cannot borrow `**other` as mutable more than once at a time [E0499]
         };
 
         let c = other;
diff --git a/tests/ui/nll/polonius/array-literal-index-oob-2024.rs b/tests/ui/nll/polonius/array-literal-index-oob-2024.rs
new file mode 100644
index 00000000000..2054a32e535
--- /dev/null
+++ b/tests/ui/nll/polonius/array-literal-index-oob-2024.rs
@@ -0,0 +1,12 @@
+// This test used to ICE under `-Zpolonius=next` when computing loan liveness
+// and taking kills into account during reachability traversal of the localized
+// constraint graph. Originally from another test but on edition 2024, as
+// seen in issue #135646.
+
+//@ compile-flags: -Zpolonius=next
+//@ edition: 2024
+//@ check-pass
+
+fn main() {
+    &{ [1, 2, 3][4] };
+}
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.rs b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
new file mode 100644
index 00000000000..c5571f131da
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
@@ -0,0 +1,34 @@
+// An example (from @steffahn) of reachability as an approximation of liveness where the polonius
+// alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+use std::cell::Cell;
+
+struct Invariant<'l>(Cell<&'l ()>);
+
+fn create_invariant<'l>() -> Invariant<'l> {
+    Invariant(Cell::new(&()))
+}
+
+fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+    //[nll]~^ ERROR lifetime may not live long enough
+    //[nll]~| ERROR lifetime may not live long enough
+    //[polonius]~^^^ ERROR lifetime may not live long enough
+    //[polonius]~| ERROR lifetime may not live long enough
+}
+
+fn use_it_but_its_the_same_region<'a: 'b, 'b: 'a>(
+    choice: bool,
+) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+}
+
+fn main() {}
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
index 7ac4e5de283..b768f60590c 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `*elements` as mutable more than once at a time
-  --> $DIR/iterating-updating-cursor-issue-108704.rs:40:26
+  --> $DIR/iterating-updating-cursor-issue-108704.rs:41:26
    |
 LL |         for (idx, el) in elements.iter_mut().enumerate() {
    |                          ^^^^^^^^
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr
new file mode 100644
index 00000000000..b768f60590c
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*elements` as mutable more than once at a time
+  --> $DIR/iterating-updating-cursor-issue-108704.rs:41:26
+   |
+LL |         for (idx, el) in elements.iter_mut().enumerate() {
+   |                          ^^^^^^^^
+   |                          |
+   |                          `*elements` was mutably borrowed here in the previous iteration of the loop
+   |                          first borrow used here, in later iteration of loop
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
index 420cb73bed2..673efa8f225 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #108704 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #108704 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #108704
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #108704
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -32,7 +33,7 @@ fn merge_tree_ok(root: &mut Root, path: Vec<String>) {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn merge_tree_ko(root: &mut Root, path: Vec<String>) {
     let mut elements = &mut root.children;
 
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
index 14e1726e158..34b04e707db 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `p.0` as mutable more than once at a time
-  --> $DIR/iterating-updating-cursor-issue-57165.rs:29:20
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:20
    |
 LL |     while let Some(now) = p {
    |                    ^^^    - first borrow used here, in later iteration of loop
@@ -7,7 +7,7 @@ LL |     while let Some(now) = p {
    |                    `p.0` was mutably borrowed here in the previous iteration of the loop
 
 error[E0503]: cannot use `*p` because it was mutably borrowed
-  --> $DIR/iterating-updating-cursor-issue-57165.rs:29:27
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:27
    |
 LL |     while let Some(now) = p {
    |                    ---    ^
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr
new file mode 100644
index 00000000000..34b04e707db
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr
@@ -0,0 +1,22 @@
+error[E0499]: cannot borrow `p.0` as mutable more than once at a time
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:20
+   |
+LL |     while let Some(now) = p {
+   |                    ^^^    - first borrow used here, in later iteration of loop
+   |                    |
+   |                    `p.0` was mutably borrowed here in the previous iteration of the loop
+
+error[E0503]: cannot use `*p` because it was mutably borrowed
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:27
+   |
+LL |     while let Some(now) = p {
+   |                    ---    ^
+   |                    |      |
+   |                    |      use of borrowed `p.0`
+   |                    |      borrow later used here
+   |                    `p.0` is borrowed here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
index 63ec89146d4..9670fc77e6f 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #57165 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #57165 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #57165
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #57165
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -22,7 +23,7 @@ fn no_control_flow() {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn conditional() {
     let mut b = Some(Box::new(X { next: None }));
     let mut p = &mut b;
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
index bf38da566c6..b76e4ff6398 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `*node_ref` because it is borrowed
-  --> $DIR/iterating-updating-cursor-issue-63908.rs:42:5
+  --> $DIR/iterating-updating-cursor-issue-63908.rs:43:5
    |
 LL | fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
    |                                                - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr
new file mode 100644
index 00000000000..b76e4ff6398
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr
@@ -0,0 +1,18 @@
+error[E0506]: cannot assign to `*node_ref` because it is borrowed
+  --> $DIR/iterating-updating-cursor-issue-63908.rs:43:5
+   |
+LL | fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
+   |                                                - let's call the lifetime of this reference `'1`
+LL |     loop {
+LL |         let next_ref = &mut node_ref.as_mut().unwrap().next;
+   |                             -------- `*node_ref` is borrowed here
+...
+LL |             node_ref = next_ref;
+   |             ------------------- assignment requires that `*node_ref` is borrowed for `'1`
+...
+LL |     *node_ref = None;
+   |     ^^^^^^^^^ `*node_ref` is assigned to here but it was already borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
index 00e48b65fed..6682926c523 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #63908 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #63908 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #63908
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #63908
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -27,7 +28,7 @@ fn remove_last_node_recursive<T>(node_ref: &mut List<T>) {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
     loop {
         let next_ref = &mut node_ref.as_mut().unwrap().next;
diff --git a/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr b/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr
new file mode 100644
index 00000000000..941c736d8d2
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `self.buf_read` as mutable more than once at a time
+  --> $DIR/iterating-updating-mutref.rs:61:23
+   |
+LL |     pub fn next<'a>(&'a mut self) -> &'a str {
+   |                 -- lifetime `'a` defined here
+LL |         loop {
+LL |             let buf = self.buf_read.fill_buf();
+   |                       ^^^^^^^^^^^^^ `self.buf_read` was mutably borrowed here in the previous iteration of the loop
+LL |             if let Some(s) = decode(buf) {
+LL |                 return s;
+   |                        - returning this value requires that `self.buf_read` is borrowed for `'a`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-mutref.rs b/tests/ui/nll/polonius/iterating-updating-mutref.rs
new file mode 100644
index 00000000000..a315bf66279
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-mutref.rs
@@ -0,0 +1,87 @@
+// These are some examples of iterating through and updating a mutable ref, similar in spirit to the
+// linked-list-like pattern of #46859/#48001 where the polonius alpha analysis shows imprecision,
+// unlike the datalog implementation.
+//
+// They differ in that after the loans prior to the loop are either not live after the loop, or with
+// control flow and outlives relationships that are simple enough for the reachability
+// approximation. They're thus accepted by the alpha analysis, like NLLs did for the simplest cases
+// of flow-sensitivity.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [nll] known-bug: #46859
+//@ [polonius] check-pass
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+// The #46859 OP
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+fn to_refs<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// A similar construction, where paths in the constraint graph are also clearly terminating, so it's
+// fine even for NLLs.
+fn to_refs2<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            break;
+        }
+    }
+
+    result
+}
+
+// Another MCVE from the same issue, but was rejected by NLLs.
+pub struct Decoder {
+    buf_read: BufRead,
+}
+
+impl Decoder {
+    // NLLs fail here
+    pub fn next<'a>(&'a mut self) -> &'a str {
+        loop {
+            let buf = self.buf_read.fill_buf();
+            if let Some(s) = decode(buf) {
+                return s;
+            }
+            // loop to get more input data
+
+            // At this point `buf` is not used anymore.
+            // With NLL I would expect the borrow to end here,
+            // such that `self.buf_read` is not borrowed anymore
+            // by the time we start the next loop iteration.
+        }
+    }
+}
+
+struct BufRead;
+
+impl BufRead {
+    fn fill_buf(&mut self) -> &[u8] {
+        unimplemented!()
+    }
+}
+
+fn decode(_: &[u8]) -> Option<&str> {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
new file mode 100644
index 00000000000..bf8546b63bf
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
@@ -0,0 +1,26 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `<T as LendingIterator>::Item<'_>`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
new file mode 100644
index 00000000000..ae8cc78957f
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
@@ -0,0 +1,71 @@
+// Some sanity checks for lending iterators with GATs. This is just some non-regression tests
+// ensuring the polonius alpha analysis, the datalog implementation, and NLLs agree in these common
+// cases of overlapping yielded items.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+trait LendingIterator {
+    type Item<'a>
+    where
+        Self: 'a;
+    fn next(&mut self) -> Option<Self::Item<'_>>;
+}
+
+fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+    let Some(i) = t.next() else { return None };
+    let Some(j) = t.next() else { return None };
+    //~^ ERROR cannot borrow `*t` as mutable more than once at a time
+
+    // `i` is obviously still (use-)live here, but we called `next` again to get `j`.
+    Some((i, j))
+}
+
+fn drop_live<T: LendingIterator>(t: &mut T) {
+    let i = t.next();
+
+    // Now `i` is use-dead here, but we don't know if the iterator items have a `Drop` impl, so it's
+    // still drop-live.
+    let j = t.next();
+    //~^ ERROR cannot borrow `*t` as mutable more than once at a time
+}
+
+// But we can still manually serialize the lifetimes with scopes (or preventing the destructor from
+// being called), so they're not overlapping.
+fn manually_non_overlapping<T: LendingIterator>(t: &mut T) {
+    {
+        let i = t.next();
+    }
+
+    let j = t.next(); // i is dead
+
+    drop(j);
+    let k = t.next(); // j is dead
+
+    let k = std::mem::ManuallyDrop::new(k);
+    let l = t.next(); // we told the compiler that k is not drop-live
+}
+
+// The cfg below is because there's a diagnostic ICE trying to explain the source of the error when
+// using the datalog implementation. We're not fixing *that*, outside of removing the implementation
+// in the future.
+#[cfg(not(legacy))] // FIXME: remove this cfg when removing the datalog implementation
+fn items_have_no_borrows<T: LendingIterator>(t: &mut T)
+where
+    for<'a> T::Item<'a>: 'static,
+{
+    let i = t.next();
+    let j = t.next();
+}
+
+fn items_are_copy<T: LendingIterator>(t: &mut T)
+where
+    for<'a> T::Item<'a>: Copy,
+{
+    let i = t.next();
+    let j = t.next();
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-15043.rs b/tests/ui/parser/generics-rangle-eq-15043.rs
index a9bb46b649b..1afc334dfd8 100644
--- a/tests/ui/issues/issue-15043.rs
+++ b/tests/ui/parser/generics-rangle-eq-15043.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15043
+
 //@ run-pass
 
 #![allow(warnings)]
diff --git a/tests/ui/issues/issue-15896.rs b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs
index d3153b516e6..9f7c5084c0e 100644
--- a/tests/ui/issues/issue-15896.rs
+++ b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15896
+
 // Regression test for #15896. It used to ICE rustc.
 
 fn main() {
diff --git a/tests/ui/issues/issue-15896.stderr b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr
index 381f6dc2276..8dee4c37e2f 100644
--- a/tests/ui/issues/issue-15896.stderr
+++ b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-15896.rs:11:11
+  --> $DIR/enum-struct-pattern-mismatch-15896.rs:13:11
    |
 LL |     let u = match e {
    |                   - this expression has type `E`
diff --git a/tests/ui/issues/issue-15381.rs b/tests/ui/pattern/refutable-pattern-for-loop-15381.rs
index bd5f62ddc67..3c19612c9cc 100644
--- a/tests/ui/issues/issue-15381.rs
+++ b/tests/ui/pattern/refutable-pattern-for-loop-15381.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15381
+
 fn main() {
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
diff --git a/tests/ui/issues/issue-15381.stderr b/tests/ui/pattern/refutable-pattern-for-loop-15381.stderr
index 03a0100f1bd..3c1d5fb454c 100644
--- a/tests/ui/issues/issue-15381.stderr
+++ b/tests/ui/pattern/refutable-pattern-for-loop-15381.stderr
@@ -1,5 +1,5 @@
 error[E0005]: refutable pattern in `for` loop binding
-  --> $DIR/issue-15381.rs:4:9
+  --> $DIR/refutable-pattern-for-loop-15381.rs:6:9
    |
 LL |     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
    |         ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
diff --git a/tests/ui/issues/issue-15104.rs b/tests/ui/pattern/slice-pattern-recursion-15104.rs
index e68c94c370e..24e3fe78de0 100644
--- a/tests/ui/issues/issue-15104.rs
+++ b/tests/ui/pattern/slice-pattern-recursion-15104.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15104
+
 //@ run-pass
 
 fn main() {
diff --git a/tests/ui/issues/issue-16149.rs b/tests/ui/pattern/static-binding-shadow-16149.rs
index 51b60725c5a..a46f78214c7 100644
--- a/tests/ui/issues/issue-16149.rs
+++ b/tests/ui/pattern/static-binding-shadow-16149.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16149
+
 extern "C" {
     static externalValue: isize;
 }
diff --git a/tests/ui/issues/issue-16149.stderr b/tests/ui/pattern/static-binding-shadow-16149.stderr
index 9ffd0e7e645..6d8c7634acd 100644
--- a/tests/ui/issues/issue-16149.stderr
+++ b/tests/ui/pattern/static-binding-shadow-16149.stderr
@@ -1,5 +1,5 @@
 error[E0530]: match bindings cannot shadow statics
-  --> $DIR/issue-16149.rs:7:9
+  --> $DIR/static-binding-shadow-16149.rs:9:9
    |
 LL |     static externalValue: isize;
    |     ---------------------------- the static `externalValue` is defined here
diff --git a/tests/ui/issues/issue-15260.rs b/tests/ui/pattern/struct-field-duplicate-binding-15260.rs
index 64fc3df3d23..a3617798cdf 100644
--- a/tests/ui/issues/issue-15260.rs
+++ b/tests/ui/pattern/struct-field-duplicate-binding-15260.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15260
+
 struct Foo {
     a: usize,
 }
diff --git a/tests/ui/issues/issue-15260.stderr b/tests/ui/pattern/struct-field-duplicate-binding-15260.stderr
index 4a3041122b2..536904fbcb3 100644
--- a/tests/ui/issues/issue-15260.stderr
+++ b/tests/ui/pattern/struct-field-duplicate-binding-15260.stderr
@@ -1,5 +1,5 @@
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:8:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:10:9
    |
 LL |         a: _,
    |         ---- first use of `a`
@@ -7,7 +7,7 @@ LL |         a: _
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:14:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:16:9
    |
 LL |         a,
    |         - first use of `a`
@@ -15,7 +15,7 @@ LL |         a: _
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:20:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:22:9
    |
 LL |         a,
    |         - first use of `a`
@@ -23,7 +23,7 @@ LL |         a: _,
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:22:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:24:9
    |
 LL |         a,
    |         - first use of `a`
diff --git a/tests/ui/issues/issue-15129-rpass.rs b/tests/ui/pattern/tuple-enum-match-15129.rs
index e2ddb989072..1d6192c4cb3 100644
--- a/tests/ui/issues/issue-15129-rpass.rs
+++ b/tests/ui/pattern/tuple-enum-match-15129.rs
@@ -1,24 +1,25 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15129
+
 //@ run-pass
 
 pub enum T {
     T1(()),
-    T2(())
+    T2(()),
 }
 
 pub enum V {
     V1(isize),
-    V2(bool)
+    V2(bool),
 }
 
 fn foo(x: (T, V)) -> String {
     match x {
-        (T::T1(()), V::V1(i))  => format!("T1(()), V1({})", i),
-        (T::T2(()), V::V2(b))  => format!("T2(()), V2({})", b),
-        _ => String::new()
+        (T::T1(()), V::V1(i)) => format!("T1(()), V1({})", i),
+        (T::T2(()), V::V2(b)) => format!("T2(()), V2({})", b),
+        _ => String::new(),
     }
 }
 
-
 fn main() {
     assert_eq!(foo((T::T1(()), V::V1(99))), "T1(()), V1(99)".to_string());
     assert_eq!(foo((T::T2(()), V::V2(true))), "T2(()), V2(true)".to_string());
diff --git a/tests/ui/issues/issue-16401.rs b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs
index 0985a6806d2..2eba33e177e 100644
--- a/tests/ui/issues/issue-16401.rs
+++ b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16401
+
 struct Slice<T> {
     data: *const T,
     len: usize,
diff --git a/tests/ui/issues/issue-16401.stderr b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr
index 6af920ca439..22c04e439c4 100644
--- a/tests/ui/issues/issue-16401.stderr
+++ b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-16401.rs:8:9
+  --> $DIR/unit-type-struct-pattern-mismatch-16401.rs:10:9
    |
 LL |     match () {
    |           -- this expression has type `()`
diff --git a/tests/ui/issues/issue-16452.rs b/tests/ui/statics/conditional-static-declaration-16010.rs
index 4ab74f09059..0bc5b0ee86f 100644
--- a/tests/ui/issues/issue-16452.rs
+++ b/tests/ui/statics/conditional-static-declaration-16010.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16010
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/issues/issue-15444.rs b/tests/ui/traits/fn-type-trait-impl-15444.rs
index 14708c7733c..ab91e88b9cd 100644
--- a/tests/ui/issues/issue-15444.rs
+++ b/tests/ui/traits/fn-type-trait-impl-15444.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15444
+
 //@ run-pass
 
 trait MyTrait {
diff --git a/tests/ui/issues/issue-15734.rs b/tests/ui/traits/index-trait-multiple-impls-15734.rs
index 26fb7061664..a2d5d7c87fc 100644
--- a/tests/ui/issues/issue-15734.rs
+++ b/tests/ui/traits/index-trait-multiple-impls-15734.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15734
+
 //@ run-pass
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
diff --git a/tests/ui/issues/issue-16048.rs b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs
index eaf6acff26b..9c36b231403 100644
--- a/tests/ui/issues/issue-16048.rs
+++ b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16048
+
 trait NoLifetime {
     fn get<'p, T : Test<'p>>(&self) -> T;
     //~^ NOTE lifetimes in impl do not match this method in trait
diff --git a/tests/ui/issues/issue-16048.stderr b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr
index f97f13152bc..08b69184b7f 100644
--- a/tests/ui/issues/issue-16048.stderr
+++ b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr
@@ -1,5 +1,5 @@
 error[E0195]: lifetime parameters or bounds on method `get` do not match the trait declaration
-  --> $DIR/issue-16048.rs:21:11
+  --> $DIR/lifetime-mismatch-trait-impl-16048.rs:23:11
    |
 LL |     fn get<'p, T : Test<'p>>(&self) -> T;
    |           ------------------ lifetimes in impl do not match this method in trait
@@ -8,7 +8,7 @@ LL |     fn get<'p, T: Test<'a> + From<Foo<'a>>>(&self) -> T {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
 
 error[E0605]: non-primitive cast: `Foo<'a>` as `T`
-  --> $DIR/issue-16048.rs:24:16
+  --> $DIR/lifetime-mismatch-trait-impl-16048.rs:26:16
    |
 LL |         return *self as T;
    |                ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.nll.stderr
index 07304cd448e..dcade3aa367 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/tests/ui/wf/hir-wf-check-erase-regions.nll.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:7:21
+  --> $DIR/hir-wf-check-erase-regions.rs:11:21
    |
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -11,7 +11,7 @@ note: required by a bound in `std::iter::IntoIterator::IntoIter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
 
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:7:5
+  --> $DIR/hir-wf-check-erase-regions.rs:11:5
    |
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |     ^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -23,7 +23,7 @@ note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
    |
 LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -35,7 +35,7 @@ note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
 error[E0277]: `&T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
    |
 LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr b/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr
new file mode 100644
index 00000000000..55728aa642b
--- /dev/null
+++ b/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr
@@ -0,0 +1,39 @@
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:21
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `Flatten<std::slice::Iter<'a, T>>` to implement `Iterator`
+note: required by a bound in `std::iter::IntoIterator::IntoIter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:5
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |     ^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&'a T` to implement `IntoIterator`
+note: required by a bound in `Flatten`
+  --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&'a T` to implement `IntoIterator`
+note: required by a bound in `Flatten`
+  --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs
index 20cc1cfe730..ef9132697ef 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.rs
+++ b/tests/ui/wf/hir-wf-check-erase-regions.rs
@@ -1,6 +1,10 @@
 // Regression test for #87549.
 //@ incremental
 
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius
+//@ [polonius] compile-flags: -Zpolonius=next
+
 pub struct Table<T, const N: usize>([Option<T>; N]);
 
 impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
@@ -10,7 +14,7 @@ impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
 
     fn into_iter(self) -> Self::IntoIter {
         //~^ ERROR `&'a T` is not an iterator
-        //~| ERROR `&T` is not an iterator
+        //[nll]~| ERROR `&T` is not an iterator
         unimplemented!()
     }
 }
diff --git a/triagebot.toml b/triagebot.toml
index 7b1325899f3..71f1ed0fda3 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1573,7 +1573,7 @@ changelog-branch = "master"
 [note]
 
 [behind-upstream]
-days-threshold = 14
+days-threshold = 28
 
 # Canonicalize issue numbers to avoid closing the wrong issue
 # when commits are included in subtrees, as well as warning links in commits.