about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs33
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs3
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs33
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0502.md5
-rw-r--r--compiler/rustc_expand/src/config.rs29
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs74
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs91
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs1
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs266
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs1
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs6
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs36
-rw-r--r--compiler/rustc_infer/src/infer/relate/generalize.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs2
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs2
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs2
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/relate/type_relating.rs4
-rw-r--r--compiler/rustc_infer/src/traits/util.rs49
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs34
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs7
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs12
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs17
-rw-r--r--compiler/rustc_next_trait_solver/src/lib.rs1
-rw-r--r--compiler/rustc_next_trait_solver/src/relate.rs15
-rw-r--r--compiler/rustc_next_trait_solver/src/relate/combine.rs34
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs6
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs53
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs17
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs23
-rw-r--r--compiler/rustc_resolve/src/late.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--compiler/rustc_resolve/src/macros.rs9
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_type_ir/src/inherent.rs8
-rw-r--r--compiler/rustc_type_ir/src/interner.rs3
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_type_ir/src/outlives.rs335
-rw-r--r--library/alloc/src/collections/linked_list.rs20
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs30
-rw-r--r--library/alloc/src/collections/vec_deque/spec_extend.rs13
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/sync.rs8
-rw-r--r--library/alloc/src/vec/mod.rs20
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/ffi/mod.rs414
-rw-r--r--library/core/src/ffi/va_list.rs301
-rw-r--r--library/core/src/iter/traits/collect.rs122
-rw-r--r--library/core/src/mem/mod.rs14
-rw-r--r--library/core/src/ptr/const_ptr.rs126
-rw-r--r--library/core/src/ptr/mut_ptr.rs126
-rw-r--r--library/core/src/ptr/non_null.rs131
-rw-r--r--library/std/src/path.rs13
-rw-r--r--library/std/src/path/tests.rs35
-rw-r--r--library/std/src/sync/once_lock.rs19
-rw-r--r--src/bootstrap/src/core/build_steps/clean.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs30
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs265
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs38
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs38
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/perf.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/run.rs19
-rw-r--r--src/bootstrap/src/core/build_steps/suggest.rs12
-rw-r--r--src/bootstrap/src/core/build_steps/synthetic_targets.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs120
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs17
-rw-r--r--src/bootstrap/src/core/build_steps/vendor.rs6
-rw-r--r--src/bootstrap/src/core/builder.rs17
-rw-r--r--src/bootstrap/src/core/download.rs4
-rw-r--r--src/bootstrap/src/core/metadata.rs6
-rw-r--r--src/bootstrap/src/core/sanity.rs9
-rw-r--r--src/bootstrap/src/lib.rs71
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs6
-rw-r--r--src/bootstrap/src/utils/exec.rs29
-rw-r--r--src/bootstrap/src/utils/helpers.rs10
-rw-r--r--src/bootstrap/src/utils/tarball.rs2
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md2
-rw-r--r--src/librustdoc/html/static/js/search.js18
m---------src/tools/cargo0
-rw-r--r--src/tools/run-make-support/src/diff/mod.rs34
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt2
-rw-r--r--src/tools/tidy/src/pal.rs2
-rw-r--r--src/tools/tidy/src/style.rs3
-rw-r--r--tests/crashes/125099.rs24
-rw-r--r--tests/crashes/127332.rs9
-rw-r--r--tests/run-make/emit-path-unhashed/Makefile37
-rw-r--r--tests/run-make/emit-path-unhashed/rmake.rs34
-rw-r--r--tests/run-make/emit-shared-files/Makefile46
-rw-r--r--tests/run-make/emit-shared-files/rmake.rs102
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.stderr12
-rw-r--r--tests/ui/async-await/in-trait/async-generics.stderr12
-rw-r--r--tests/ui/compare-method/bad-self-type.stderr2
-rw-r--r--tests/ui/consts/offset_from_ub.rs8
-rw-r--r--tests/ui/consts/offset_from_ub.stderr16
-rw-r--r--tests/ui/error-codes/E0308.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr4
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr4
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr2
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr173
-rw-r--r--tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs51
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.rs4
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr4
-rw-r--r--tests/ui/impl-trait/trait_type.stderr2
-rw-r--r--tests/ui/lang-items/start_lang_item_args.missing_ret.stderr2
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs12
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs6
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr6
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs78
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr107
-rw-r--r--tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs14
-rw-r--r--tests/ui/macros/out-of-scope-calls-false-positives.rs10
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr2
-rw-r--r--tests/ui/method-output-diff-issue-127263.rs8
-rw-r--r--tests/ui/method-output-diff-issue-127263.stderr25
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr (renamed from tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr)20
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr116
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs46
-rw-r--r--tests/ui/panic-handler/panic-handler-bad-signature-1.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs3
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr12
-rw-r--r--tests/ui/traits/impl-method-mismatch.stderr2
-rw-r--r--tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr4
-rw-r--r--tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.next.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.next.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.rs6
-rw-r--r--tests/ui/typeck/ice-with-expr-not-struct-127332.rs15
-rw-r--r--tests/ui/typeck/ice-with-expr-not-struct-127332.stderr9
-rw-r--r--tests/ui/typeck/ptr-null-mutability-suggestions.stderr10
166 files changed, 2736 insertions, 1982 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d1889fb6861..afeb9faec09 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4168,6 +4168,7 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
+ "rustc_next_trait_solver",
  "rustc_span",
  "rustc_target",
  "rustc_type_ir",
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 2cf811e9122..7754ca0a0f5 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -10,8 +10,6 @@ use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
 use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
 use crate::{AttrVec, Attribute, Stmt, StmtKind};
 
-use rustc_span::Span;
-
 use std::fmt;
 use std::marker::PhantomData;
 
@@ -91,37 +89,6 @@ impl<T: AstDeref<Target: HasNodeId>> HasNodeId for T {
     }
 }
 
-/// A trait for AST nodes having a span.
-pub trait HasSpan {
-    fn span(&self) -> Span;
-}
-
-macro_rules! impl_has_span {
-    ($($T:ty),+ $(,)?) => {
-        $(
-            impl HasSpan for $T {
-                fn span(&self) -> Span {
-                    self.span
-                }
-            }
-        )+
-    };
-}
-
-impl_has_span!(AssocItem, Block, Expr, ForeignItem, Item, Pat, Path, Stmt, Ty, Visibility);
-
-impl<T: AstDeref<Target: HasSpan>> HasSpan for T {
-    fn span(&self) -> Span {
-        self.ast_deref().span()
-    }
-}
-
-impl HasSpan for AttrItem {
-    fn span(&self) -> Span {
-        self.span()
-    }
-}
-
 /// A trait for AST nodes having (or not having) collected tokens.
 pub trait HasTokens {
     fn tokens(&self) -> Option<&LazyAttrTokenStream>;
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 65f1b5dbaf5..088ae9ba441 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -202,7 +202,8 @@ impl Attribute {
         }
     }
 
-    pub fn tokens(&self) -> TokenStream {
+    // Named `get_tokens` to distinguish it from the `<Attribute as HasTokens>::tokens` method.
+    pub fn get_tokens(&self) -> TokenStream {
         match &self.kind {
             AttrKind::Normal(normal) => TokenStream::new(
                 normal
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 7ca950e50e6..846a108091f 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -44,7 +44,7 @@ pub mod tokenstream;
 pub mod visit;
 
 pub use self::ast::*;
-pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens};
+pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index f816375b912..cbf21317f1a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -704,7 +704,7 @@ fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
             visit_attr_tts(tts, vis);
             visit_delim_span(dspan, vis);
         }
-        AttrTokenTree::Attributes(AttributesData { attrs, tokens }) => {
+        AttrTokenTree::AttrsTarget(AttrsTarget { attrs, tokens }) => {
             visit_attrs(attrs, vis);
             visit_lazy_tts_opt_mut(Some(tokens), vis);
         }
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 655c18e4559..ee068f19332 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -14,7 +14,7 @@
 //! ownership of the original.
 
 use crate::ast::{AttrStyle, StmtKind};
-use crate::ast_traits::{HasAttrs, HasSpan, HasTokens};
+use crate::ast_traits::{HasAttrs, HasTokens};
 use crate::token::{self, Delimiter, Nonterminal, Token, TokenKind};
 use crate::AttrVec;
 
@@ -170,8 +170,8 @@ pub enum AttrTokenTree {
     Delimited(DelimSpan, DelimSpacing, Delimiter, AttrTokenStream),
     /// Stores the attributes for an attribute target,
     /// along with the tokens for that attribute target.
-    /// See `AttributesData` for more information
-    Attributes(AttributesData),
+    /// See `AttrsTarget` for more information
+    AttrsTarget(AttrsTarget),
 }
 
 impl AttrTokenStream {
@@ -180,7 +180,7 @@ impl AttrTokenStream {
     }
 
     /// Converts this `AttrTokenStream` to a plain `Vec<TokenTree>`.
-    /// During conversion, `AttrTokenTree::Attributes` get 'flattened'
+    /// During conversion, `AttrTokenTree::AttrsTarget` get 'flattened'
     /// back to a `TokenStream` of the form `outer_attr attr_target`.
     /// If there are inner attributes, they are inserted into the proper
     /// place in the attribute target tokens.
@@ -199,13 +199,13 @@ impl AttrTokenStream {
                         TokenStream::new(stream.to_token_trees()),
                     ))
                 }
-                AttrTokenTree::Attributes(data) => {
-                    let idx = data
+                AttrTokenTree::AttrsTarget(target) => {
+                    let idx = target
                         .attrs
                         .partition_point(|attr| matches!(attr.style, crate::AttrStyle::Outer));
-                    let (outer_attrs, inner_attrs) = data.attrs.split_at(idx);
+                    let (outer_attrs, inner_attrs) = target.attrs.split_at(idx);
 
-                    let mut target_tokens = data.tokens.to_attr_token_stream().to_token_trees();
+                    let mut target_tokens = target.tokens.to_attr_token_stream().to_token_trees();
                     if !inner_attrs.is_empty() {
                         let mut found = false;
                         // Check the last two trees (to account for a trailing semi)
@@ -227,7 +227,7 @@ impl AttrTokenStream {
 
                                 let mut stream = TokenStream::default();
                                 for inner_attr in inner_attrs {
-                                    stream.push_stream(inner_attr.tokens());
+                                    stream.push_stream(inner_attr.get_tokens());
                                 }
                                 stream.push_stream(delim_tokens.clone());
                                 *tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
@@ -242,7 +242,7 @@ impl AttrTokenStream {
                         );
                     }
                     for attr in outer_attrs {
-                        res.extend(attr.tokens().0.iter().cloned());
+                        res.extend(attr.get_tokens().0.iter().cloned());
                     }
                     res.extend(target_tokens);
                 }
@@ -262,7 +262,7 @@ impl AttrTokenStream {
 /// have an `attrs` field containing the `#[cfg(FALSE)]` attr,
 /// and a `tokens` field storing the (unparsed) tokens `struct Foo {}`
 #[derive(Clone, Debug, Encodable, Decodable)]
-pub struct AttributesData {
+pub struct AttrsTarget {
     /// Attributes, both outer and inner.
     /// These are stored in the original order that they were parsed in.
     pub attrs: AttrVec,
@@ -436,17 +436,17 @@ impl TokenStream {
         TokenStream::new(vec![TokenTree::token_alone(kind, span)])
     }
 
-    pub fn from_ast(node: &(impl HasAttrs + HasSpan + HasTokens + fmt::Debug)) -> TokenStream {
+    pub fn from_ast(node: &(impl HasAttrs + HasTokens + fmt::Debug)) -> TokenStream {
         let Some(tokens) = node.tokens() else {
-            panic!("missing tokens for node at {:?}: {:?}", node.span(), node);
+            panic!("missing tokens for node: {:?}", node);
         };
         let attrs = node.attrs();
         let attr_stream = if attrs.is_empty() {
             tokens.to_attr_token_stream()
         } else {
-            let attr_data =
-                AttributesData { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
-            AttrTokenStream::new(vec![AttrTokenTree::Attributes(attr_data)])
+            let target =
+                AttrsTarget { attrs: attrs.iter().cloned().collect(), tokens: tokens.clone() };
+            AttrTokenStream::new(vec![AttrTokenTree::AttrsTarget(target)])
         };
         TokenStream::new(attr_stream.to_token_trees())
     }
@@ -765,6 +765,7 @@ mod size_asserts {
     static_assert_size!(AttrTokenStream, 8);
     static_assert_size!(AttrTokenTree, 32);
     static_assert_size!(LazyAttrTokenStream, 8);
+    static_assert_size!(Option<LazyAttrTokenStream>, 8); // must be small, used in many AST nodes
     static_assert_size!(TokenStream, 8);
     static_assert_size!(TokenTree, 32);
     // tidy-alphabetical-end
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index b9a82046e59..02b9c2d48b1 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,8 +1,9 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
-use rustc_infer::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
-use rustc_infer::infer::relate::{Relate, RelateResult, TypeRelation};
-use rustc_infer::infer::NllRegionVariableOrigin;
+use rustc_infer::infer::relate::{
+    PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
+};
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
 use rustc_infer::traits::solve::Goal;
 use rustc_infer::traits::Obligation;
 use rustc_middle::mir::ConstraintCategory;
@@ -522,7 +523,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
     }
 }
 
-impl<'bccx, 'tcx> PredicateEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx, 'tcx> {
+impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
     fn span(&self) -> Span {
         self.locations.span(self.type_checker.body)
     }
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 884cebf1939..b09975c0ba7 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -193,7 +193,7 @@ impl CfgEval<'_> {
 
         // Re-parse the tokens, setting the `capture_cfg` flag to save extra information
         // to the captured `AttrTokenStream` (specifically, we capture
-        // `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
+        // `AttrTokenTree::AttrsTarget` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
         let mut parser = Parser::new(&self.0.sess.psess, orig_tokens, None);
         parser.capture_cfg = true;
         match parse_annotatable_with(&mut parser) {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 1d54da267ee..d86f1a7a34f 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -301,9 +301,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                         }
                         // The signed form of the intrinsic allows this. If we interpret the
                         // difference as isize, we'll get the proper signed difference. If that
-                        // seems *positive*, they were more than isize::MAX apart.
+                        // seems *positive* or equal to isize::MIN, they were more than isize::MAX apart.
                         let dist = val.to_target_isize(self)?;
-                        if dist >= 0 {
+                        if dist >= 0 || i128::from(dist) == self.pointer_size().signed_int_min() {
                             throw_ub_custom!(
                                 fluent::const_eval_offset_from_underflow,
                                 name = intrinsic_name,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0502.md b/compiler/rustc_error_codes/src/error_codes/E0502.md
index dc3ffdfddd9..85f38b9286f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0502.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0502.md
@@ -1,4 +1,5 @@
-A variable already borrowed as immutable was borrowed as mutable.
+A variable already borrowed with a certain mutability (either mutable or
+immutable) was borrowed again with a different mutability.
 
 Erroneous code example:
 
@@ -13,7 +14,7 @@ fn foo(a: &mut i32) {
 ```
 
 To fix this error, ensure that you don't have any other references to the
-variable before trying to access it mutably:
+variable before trying to access it with a different mutability:
 
 ```
 fn bar(x: &mut i32) {}
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 56cbb54fcec..40e16b45115 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -172,7 +172,7 @@ impl<'a> StripUnconfigured<'a> {
     fn configure_tokens(&self, stream: &AttrTokenStream) -> AttrTokenStream {
         fn can_skip(stream: &AttrTokenStream) -> bool {
             stream.0.iter().all(|tree| match tree {
-                AttrTokenTree::Attributes(_) => false,
+                AttrTokenTree::AttrsTarget(_) => false,
                 AttrTokenTree::Token(..) => true,
                 AttrTokenTree::Delimited(.., inner) => can_skip(inner),
             })
@@ -185,22 +185,22 @@ impl<'a> StripUnconfigured<'a> {
         let trees: Vec<_> = stream
             .0
             .iter()
-            .flat_map(|tree| match tree.clone() {
-                AttrTokenTree::Attributes(mut data) => {
-                    data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
+            .filter_map(|tree| match tree.clone() {
+                AttrTokenTree::AttrsTarget(mut target) => {
+                    target.attrs.flat_map_in_place(|attr| self.process_cfg_attr(&attr));
 
-                    if self.in_cfg(&data.attrs) {
-                        data.tokens = LazyAttrTokenStream::new(
-                            self.configure_tokens(&data.tokens.to_attr_token_stream()),
+                    if self.in_cfg(&target.attrs) {
+                        target.tokens = LazyAttrTokenStream::new(
+                            self.configure_tokens(&target.tokens.to_attr_token_stream()),
                         );
-                        Some(AttrTokenTree::Attributes(data)).into_iter()
+                        Some(AttrTokenTree::AttrsTarget(target))
                     } else {
-                        None.into_iter()
+                        None
                     }
                 }
                 AttrTokenTree::Delimited(sp, spacing, delim, mut inner) => {
                     inner = self.configure_tokens(&inner);
-                    Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)).into_iter()
+                    Some(AttrTokenTree::Delimited(sp, spacing, delim, inner))
                 }
                 AttrTokenTree::Token(
                     Token {
@@ -220,9 +220,7 @@ impl<'a> StripUnconfigured<'a> {
                 ) => {
                     panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tree);
                 }
-                AttrTokenTree::Token(token, spacing) => {
-                    Some(AttrTokenTree::Token(token, spacing)).into_iter()
-                }
+                AttrTokenTree::Token(token, spacing) => Some(AttrTokenTree::Token(token, spacing)),
             })
             .collect();
         AttrTokenStream::new(trees)
@@ -294,7 +292,7 @@ impl<'a> StripUnconfigured<'a> {
         attr: &Attribute,
         (item, item_span): (ast::AttrItem, Span),
     ) -> Attribute {
-        let orig_tokens = attr.tokens();
+        let orig_tokens = attr.get_tokens();
 
         // We are taking an attribute of the form `#[cfg_attr(pred, attr)]`
         // and producing an attribute of the form `#[attr]`. We
@@ -310,12 +308,11 @@ impl<'a> StripUnconfigured<'a> {
         else {
             panic!("Bad tokens for attribute {attr:?}");
         };
-        let pound_span = pound_token.span;
 
         // We don't really have a good span to use for the synthesized `[]`
         // in `#[attr]`, so just use the span of the `#` token.
         let bracket_group = AttrTokenTree::Delimited(
-            DelimSpan::from_single(pound_span),
+            DelimSpan::from_single(pound_token.span),
             DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
             Delimiter::Bracket,
             item.tokens
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 25958e03028..dbbd948fd70 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -1,4 +1,4 @@
-use rustc_ast::token::{self, Delimiter, IdentIsRaw};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, Token, TokenKind};
 use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
 use rustc_ast::{LitIntType, LitKind};
 use rustc_ast_pretty::pprust;
@@ -6,9 +6,10 @@ use rustc_errors::{Applicability, PResult};
 use rustc_macros::{Decodable, Encodable};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::Ident;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
 pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers";
+pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal";
 
 /// A meta-variable expression, for expansions based on properties of meta-variables.
 #[derive(Debug, PartialEq, Encodable, Decodable)]
@@ -51,11 +52,26 @@ impl MetaVarExpr {
                 let mut result = Vec::new();
                 loop {
                     let is_var = try_eat_dollar(&mut iter);
-                    let element_ident = parse_ident(&mut iter, psess, outer_span)?;
+                    let token = parse_token(&mut iter, psess, outer_span)?;
                     let element = if is_var {
-                        MetaVarExprConcatElem::Var(element_ident)
+                        MetaVarExprConcatElem::Var(parse_ident_from_token(psess, token)?)
+                    } else if let TokenKind::Literal(Lit {
+                        kind: token::LitKind::Str,
+                        symbol,
+                        suffix: None,
+                    }) = token.kind
+                    {
+                        MetaVarExprConcatElem::Literal(symbol)
                     } else {
-                        MetaVarExprConcatElem::Ident(element_ident)
+                        match parse_ident_from_token(psess, token) {
+                            Err(err) => {
+                                err.cancel();
+                                return Err(psess
+                                    .dcx()
+                                    .struct_span_err(token.span, UNSUPPORTED_CONCAT_ELEM_ERR));
+                            }
+                            Ok(elem) => MetaVarExprConcatElem::Ident(elem),
+                        }
                     };
                     result.push(element);
                     if iter.look_ahead(0).is_none() {
@@ -105,11 +121,13 @@ impl MetaVarExpr {
 
 #[derive(Debug, Decodable, Encodable, PartialEq)]
 pub(crate) enum MetaVarExprConcatElem {
-    /// There is NO preceding dollar sign, which means that this identifier should be interpreted
-    /// as a literal.
+    /// Identifier WITHOUT a preceding dollar sign, which means that this identifier should be
+    /// interpreted as a literal.
     Ident(Ident),
-    /// There is a preceding dollar sign, which means that this identifier should be expanded
-    /// and interpreted as a variable.
+    /// For example, a number or a string.
+    Literal(Symbol),
+    /// Identifier WITH a preceding dollar sign, which means that this identifier should be
+    /// expanded and interpreted as a variable.
     Var(Ident),
 }
 
@@ -158,7 +176,7 @@ fn parse_depth<'psess>(
     span: Span,
 ) -> PResult<'psess, usize> {
     let Some(tt) = iter.next() else { return Ok(0) };
-    let TokenTree::Token(token::Token { kind: token::TokenKind::Literal(lit), .. }, _) = tt else {
+    let TokenTree::Token(Token { kind: TokenKind::Literal(lit), .. }, _) = tt else {
         return Err(psess
             .dcx()
             .struct_span_err(span, "meta-variable expression depth must be a literal"));
@@ -180,12 +198,14 @@ fn parse_ident<'psess>(
     psess: &'psess ParseSess,
     fallback_span: Span,
 ) -> PResult<'psess, Ident> {
-    let Some(tt) = iter.next() else {
-        return Err(psess.dcx().struct_span_err(fallback_span, "expected identifier"));
-    };
-    let TokenTree::Token(token, _) = tt else {
-        return Err(psess.dcx().struct_span_err(tt.span(), "expected identifier"));
-    };
+    let token = parse_token(iter, psess, fallback_span)?;
+    parse_ident_from_token(psess, token)
+}
+
+fn parse_ident_from_token<'psess>(
+    psess: &'psess ParseSess,
+    token: &Token,
+) -> PResult<'psess, Ident> {
     if let Some((elem, is_raw)) = token.ident() {
         if let IdentIsRaw::Yes = is_raw {
             return Err(psess.dcx().struct_span_err(elem.span, RAW_IDENT_ERR));
@@ -205,10 +225,24 @@ fn parse_ident<'psess>(
     Err(err)
 }
 
+fn parse_token<'psess, 't>(
+    iter: &mut RefTokenTreeCursor<'t>,
+    psess: &'psess ParseSess,
+    fallback_span: Span,
+) -> PResult<'psess, &'t Token> {
+    let Some(tt) = iter.next() else {
+        return Err(psess.dcx().struct_span_err(fallback_span, UNSUPPORTED_CONCAT_ELEM_ERR));
+    };
+    let TokenTree::Token(token, _) = tt else {
+        return Err(psess.dcx().struct_span_err(tt.span(), UNSUPPORTED_CONCAT_ELEM_ERR));
+    };
+    Ok(token)
+}
+
 /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
 /// iterator is not modified and the result is `false`.
 fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
-    if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
+    if let Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
         let _ = iter.next();
         return true;
     }
@@ -218,8 +252,7 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
 /// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the
 /// iterator is not modified and the result is `false`.
 fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool {
-    if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
-    {
+    if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) {
         let _ = iter.next();
         return true;
     }
@@ -232,8 +265,7 @@ fn eat_dollar<'psess>(
     psess: &'psess ParseSess,
     span: Span,
 ) -> PResult<'psess, ()> {
-    if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
-    {
+    if let Some(TokenTree::Token(Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0) {
         let _ = iter.next();
         return Ok(());
     }
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index f935f1b77e0..9b4dc13c703 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -11,11 +11,13 @@ use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, Diag, DiagCtxtHandle, PResult};
+use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::parser::ParseNtResult;
 use rustc_session::parse::ParseSess;
+use rustc_session::parse::SymbolGallery;
 use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
-use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
+use rustc_span::{with_metavar_spans, Span, SyntaxContext};
 use smallvec::{smallvec, SmallVec};
 use std::mem;
 
@@ -312,7 +314,16 @@ pub(super) fn transcribe<'a>(
 
             // Replace meta-variable expressions with the result of their expansion.
             mbe::TokenTree::MetaVarExpr(sp, expr) => {
-                transcribe_metavar_expr(dcx, expr, interp, &mut marker, &repeats, &mut result, sp)?;
+                transcribe_metavar_expr(
+                    dcx,
+                    expr,
+                    interp,
+                    &mut marker,
+                    &repeats,
+                    &mut result,
+                    sp,
+                    &psess.symbol_gallery,
+                )?;
             }
 
             // If we are entering a new delimiter, we push its contents to the `stack` to be
@@ -669,6 +680,7 @@ fn transcribe_metavar_expr<'a>(
     repeats: &[(usize, usize)],
     result: &mut Vec<TokenTree>,
     sp: &DelimSpan,
+    symbol_gallery: &SymbolGallery,
 ) -> PResult<'a, ()> {
     let mut visited_span = || {
         let mut span = sp.entire();
@@ -680,16 +692,26 @@ fn transcribe_metavar_expr<'a>(
             let mut concatenated = String::new();
             for element in elements.into_iter() {
                 let string = match element {
-                    MetaVarExprConcatElem::Ident(ident) => ident.to_string(),
-                    MetaVarExprConcatElem::Var(ident) => extract_ident(dcx, *ident, interp)?,
+                    MetaVarExprConcatElem::Ident(elem) => elem.to_string(),
+                    MetaVarExprConcatElem::Literal(elem) => elem.as_str().into(),
+                    MetaVarExprConcatElem::Var(elem) => extract_ident(dcx, *elem, interp)?,
                 };
                 concatenated.push_str(&string);
             }
+            let symbol = nfc_normalize(&concatenated);
+            let concatenated_span = visited_span();
+            if !rustc_lexer::is_ident(symbol.as_str()) {
+                return Err(dcx.struct_span_err(
+                    concatenated_span,
+                    "`${concat(..)}` is not generating a valid identifier",
+                ));
+            }
+            symbol_gallery.insert(symbol, concatenated_span);
             // The current implementation marks the span as coming from the macro regardless of
             // contexts of the concatenated identifiers but this behavior may change in the
             // future.
             result.push(TokenTree::Token(
-                Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())),
+                Token::from_ast_ident(Ident::new(symbol, concatenated_span)),
                 Spacing::Alone,
             ));
         }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 0dbe64c3ea7..8a1ee9374c3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::{
 use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::regions::InferCtxtRegionExt;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 2230528a5ae..30ff272ce12 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -39,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
 use rustc_trait_selection::traits::{
     self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
 };
+use rustc_type_ir::solve::NoSolution;
 use rustc_type_ir::TypeFlags;
 
 use std::cell::LazyCell;
@@ -1712,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
     let cause =
         ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
 
-    let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
-
-    // `self: Self` is always valid.
-    if can_eq_self(receiver_ty) {
-        if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, receiver_ty) {
-            infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
-        }
+    // Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.
+    if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
+        let ocx = ObligationCtxt::new(wfcx.infcx);
+        ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
+        if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
+    }) {
         return true;
     }
 
@@ -1729,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
         autoderef = autoderef.include_raw_pointers();
     }
 
-    // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
-    autoderef.next();
-
     let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span));
 
     // Keep dereferencing `receiver_ty` until we get to `self_ty`.
-    loop {
-        if let Some((potential_self_ty, _)) = autoderef.next() {
-            debug!(
-                "receiver_is_valid: potential self type `{:?}` to match `{:?}`",
-                potential_self_ty, self_ty
-            );
-
-            if can_eq_self(potential_self_ty) {
-                wfcx.register_obligations(autoderef.into_obligations());
+    while let Some((potential_self_ty, _)) = autoderef.next() {
+        debug!(
+            "receiver_is_valid: potential self type `{:?}` to match `{:?}`",
+            potential_self_ty, self_ty
+        );
 
-                if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty) {
-                    infcx
-                        .err_ctxt()
-                        .report_mismatched_types(&cause, self_ty, potential_self_ty, err)
-                        .emit();
-                }
+        // Check if the self type unifies. If it does, then commit the result
+        // since it may have region side-effects.
+        if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
+            let ocx = ObligationCtxt::new(wfcx.infcx);
+            ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;
+            if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
+        }) {
+            wfcx.register_obligations(autoderef.into_obligations());
+            return true;
+        }
 
+        // Without `feature(arbitrary_self_types)`, we require that each step in the
+        // deref chain implement `receiver`.
+        if !arbitrary_self_types_enabled {
+            if !receiver_is_implemented(
+                wfcx,
+                receiver_trait_def_id,
+                cause.clone(),
+                potential_self_ty,
+            ) {
+                // We cannot proceed.
                 break;
-            } else {
-                // Without `feature(arbitrary_self_types)`, we require that each step in the
-                // deref chain implement `receiver`
-                if !arbitrary_self_types_enabled
-                    && !receiver_is_implemented(
-                        wfcx,
-                        receiver_trait_def_id,
-                        cause.clone(),
-                        potential_self_ty,
-                    )
-                {
-                    return false;
-                }
             }
-        } else {
-            debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
-            return false;
-        }
-    }
 
-    // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
-    if !arbitrary_self_types_enabled
-        && !receiver_is_implemented(wfcx, receiver_trait_def_id, cause.clone(), receiver_ty)
-    {
-        return false;
+            // Register the bound, in case it has any region side-effects.
+            wfcx.register_bound(
+                cause.clone(),
+                wfcx.param_env,
+                potential_self_ty,
+                receiver_trait_def_id,
+            );
+        }
     }
 
-    true
+    debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
+    false
 }
 
 fn receiver_is_implemented<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 2a68d3915bb..02db0352daa 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -49,6 +49,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::wf::object_region_bounds;
 use rustc_trait_selection::traits::{self, ObligationCtxt};
 
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 5086c2af3f6..08015c28a26 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -1,9 +1,9 @@
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_middle::ty::{self, Region, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_middle::{bug, span_bug};
 use rustc_span::Span;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 use smallvec::smallvec;
 
 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index ad9c1e28211..4f1c2fdd922 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AssocItem, Ty, TypeFoldable, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::ObligationCause;
 
 use super::method::probe;
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index e49b921e63c..f1ed2ade3d4 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -501,6 +501,7 @@ pub enum SuggestBoxing {
 #[suggestion(
     hir_typeck_suggest_ptr_null_mut,
     applicability = "maybe-incorrect",
+    style = "verbose",
     code = "core::ptr::null_mut()"
 )]
 pub struct SuggestPtrNullMut {
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c8ab0429ffc..193dbbbcdf4 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -734,7 +734,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 // struct; however, when EUV is run during typeck, it
                 // may not. This will generate an error earlier in typeck,
                 // so we can just ignore it.
-                span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
+                if self.cx.tainted_by_errors().is_ok() {
+                    span_bug!(with_expr.span, "with expression doesn't evaluate to a struct");
+                }
             }
         }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 047d0850d4c..10092dce587 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -40,6 +40,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, BytePos, Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 8d380caf916..fca0a3e195d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2582,7 +2582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
             (hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr), _, &ty::Ref(_, checked, _))
-                if self.can_sub(self.param_env, checked, expected) =>
+                if self.can_eq(self.param_env, checked, expected) =>
             {
                 let make_sugg = |start: Span, end: BytePos| {
                     // skip `(` for tuples such as `(c) = (&123)`.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 63b30d79aba..6a7af5510e0 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -33,6 +33,7 @@ use rustc_span::edit_distance::{
 };
 use rustc_span::symbol::sym;
 use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
 use rustc_trait_selection::traits::query::method_autoderef::{
@@ -857,7 +858,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 let args = self.fresh_args_for_item(self.span, method.def_id);
                 let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args);
                 let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
-                self.can_sub(self.param_env, fty.output(), expected)
+                self.can_eq(self.param_env, fty.output(), expected)
             }),
             _ => false,
         }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 5e0f37ed792..be526e1c26c 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -19,6 +19,7 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 use rustc_target::abi::FieldIdx;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 use ty::VariantDef;
 
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 5136ab79a0f..1f616710200 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -16,6 +16,7 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
+rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_type_ir = { path = "../rustc_type_ir" }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index a8fd3ca8c59..cebb9d09a47 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1168,14 +1168,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let output1 = sig1.output();
         let output2 = sig2.output();
         let (x1, x2) = self.cmp(output1, output2);
-        if !output1.is_unit() {
+        let output_diff = x1 != x2;
+        if !output1.is_unit() || output_diff {
             values.0.push_normal(" -> ");
             (values.0).0.extend(x1.0);
         }
-        if !output2.is_unit() {
+        if !output2.is_unit() || output_diff {
             values.1.push_normal(" -> ");
             (values.1).0.extend(x2.0);
         }
+
         values
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index fd50d1eb438..d5e7de897d0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -820,7 +820,7 @@ fn foo(&self) -> Self::T { String::new() }
                                 tcx.defaultness(item.id.owner_id)
                             {
                                 let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
-                                if self.infcx.can_eq(param_env, assoc_ty, found) {
+                                if self.infcx.can_eq_shallow(param_env, assoc_ty, found) {
                                     diag.span_label(
                                         item.span,
                                         "associated type defaults can't be assumed inside the \
@@ -843,7 +843,7 @@ fn foo(&self) -> Self::T { String::new() }
                         let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity();
                         if let hir::Defaultness::Default { has_value: true } =
                             tcx.defaultness(item.id.owner_id)
-                            && self.infcx.can_eq(param_env, assoc_ty, found)
+                            && self.infcx.can_eq_shallow(param_env, assoc_ty, found)
                         {
                             diag.span_label(
                                 item.span,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index edbb741036f..9f55939c165 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -768,19 +768,9 @@ impl<'tcx> InferCtxt<'tcx> {
             .collect()
     }
 
-    pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, expected: T, actual: T) -> bool
-    where
-        T: at::ToTrace<'tcx>,
-    {
-        let origin = &ObligationCause::dummy();
-        self.probe(|_| {
-            // We're only answering whether there could be a subtyping relation, and with
-            // opaque types, "there could be one", via registering a hidden type.
-            self.at(origin, param_env).sub(DefineOpaqueTypes::Yes, expected, actual).is_ok()
-        })
-    }
-
-    pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
+    // FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that,
+    // or we need to process the obligations.
+    pub fn can_eq_shallow<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
     where
         T: at::ToTrace<'tcx>,
     {
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
deleted file mode 100644
index 6bab3ad6ba3..00000000000
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ /dev/null
@@ -1,266 +0,0 @@
-// The outlines relation `T: 'a` or `'a: 'b`. This code frequently
-// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
-// RFC for reference.
-
-use rustc_data_structures::sso::SsoHashSet;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
-use smallvec::{smallvec, SmallVec};
-
-#[derive(Debug)]
-pub enum Component<'tcx> {
-    Region(ty::Region<'tcx>),
-    Param(ty::ParamTy),
-    Placeholder(ty::PlaceholderType),
-    UnresolvedInferenceVariable(ty::InferTy),
-
-    // Projections like `T::Foo` are tricky because a constraint like
-    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
-    // where-clause that says `T::Foo: 'a`, or the defining trait may
-    // include a bound like `type Foo: 'static`, or -- in the most
-    // conservative way -- we can prove that `T: 'a` (more generally,
-    // that all components in the projection outlive `'a`). This code
-    // is not in a position to judge which is the best technique, so
-    // we just product the projection as a component and leave it to
-    // the consumer to decide (but see `EscapingProjection` below).
-    Alias(ty::AliasTy<'tcx>),
-
-    // In the case where a projection has escaping regions -- meaning
-    // regions bound within the type itself -- we always use
-    // the most conservative rule, which requires that all components
-    // outlive the bound. So for example if we had a type like this:
-    //
-    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
-    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
-    //
-    // then the inner projection (underlined) has an escaping region
-    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
-    // outlives `'b: 'c`, and we don't consider whether the trait
-    // declares that `Foo: 'static` etc. Therefore, we just return the
-    // free components of such a projection (in this case, `'b`).
-    //
-    // However, in the future, we may want to get smarter, and
-    // actually return a "higher-ranked projection" here. Therefore,
-    // we mark that these components are part of an escaping
-    // projection, so that implied bounds code can avoid relying on
-    // them. This gives us room to improve the regionck reasoning in
-    // the future without breaking backwards compat.
-    EscapingAlias(Vec<Component<'tcx>>),
-}
-
-/// Push onto `out` all the things that must outlive `'a` for the condition
-/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-pub fn push_outlives_components<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    ty0: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-) {
-    let mut visited = SsoHashSet::new();
-    compute_components(tcx, ty0, out, &mut visited);
-    debug!("components({:?}) = {:?}", ty0, out);
-}
-
-fn compute_components<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    // Descend through the types, looking for the various "base"
-    // components and collecting them into `out`. This is not written
-    // with `collect()` because of the need to sometimes skip subtrees
-    // in the `subtys` iterator (e.g., when encountering a
-    // projection).
-    match *ty.kind() {
-            ty::FnDef(_, args) => {
-                // HACK(eddyb) ignore lifetimes found shallowly in `args`.
-                // This is inconsistent with `ty::Adt` (including all args)
-                // and with `ty::Closure` (ignoring all args other than
-                // upvars, of which a `ty::FnDef` doesn't have any), but
-                // consistent with previous (accidental) behavior.
-                // See https://github.com/rust-lang/rust/issues/70917
-                // for further background and discussion.
-                for child in args {
-                    match child.unpack() {
-                        GenericArgKind::Type(ty) => {
-                            compute_components(tcx, ty, out, visited);
-                        }
-                        GenericArgKind::Lifetime(_) => {}
-                        GenericArgKind::Const(_) => {
-                            compute_components_recursive(tcx, child, out, visited);
-                        }
-                    }
-                }
-            }
-
-            ty::Pat(element, _) |
-            ty::Array(element, _) => {
-                // Don't look into the len const as it doesn't affect regions
-                compute_components(tcx, element, out, visited);
-            }
-
-            ty::Closure(_, args) => {
-                let tupled_ty = args.as_closure().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-            }
-
-            ty::CoroutineClosure(_, args) => {
-                let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-            }
-
-            ty::Coroutine(_, args) => {
-                // Same as the closure case
-                let tupled_ty = args.as_coroutine().tupled_upvars_ty();
-                compute_components(tcx, tupled_ty, out, visited);
-
-                // We ignore regions in the coroutine interior as we don't
-                // want these to affect region inference
-            }
-
-            // All regions are bound inside a witness
-            ty::CoroutineWitness(..) => (),
-
-            // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
-            // is implied by the environment is done in regionck.
-            ty::Param(p) => {
-                out.push(Component::Param(p));
-            }
-
-            ty::Placeholder(p) => {
-                out.push(Component::Placeholder(p));
-            }
-
-            // For projections, we prefer to generate an obligation like
-            // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
-            // regionck more ways to prove that it holds. However,
-            // regionck is not (at least currently) prepared to deal with
-            // higher-ranked regions that may appear in the
-            // trait-ref. Therefore, if we see any higher-ranked regions,
-            // we simply fallback to the most restrictive rule, which
-            // requires that `Pi: 'a` for all `i`.
-            ty::Alias(_, alias_ty) => {
-                if !alias_ty.has_escaping_bound_vars() {
-                    // best case: no escaping regions, so push the
-                    // projection and skip the subtree (thus generating no
-                    // constraints for Pi). This defers the choice between
-                    // the rules OutlivesProjectionEnv,
-                    // OutlivesProjectionTraitDef, and
-                    // OutlivesProjectionComponents to regionck.
-                    out.push(Component::Alias(alias_ty));
-                } else {
-                    // fallback case: hard code
-                    // OutlivesProjectionComponents. Continue walking
-                    // through and constrain Pi.
-                    let mut subcomponents = smallvec![];
-                    let mut subvisited = SsoHashSet::new();
-                    compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
-                    out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
-                }
-            }
-
-            // We assume that inference variables are fully resolved.
-            // So, if we encounter an inference variable, just record
-            // the unresolved variable as a component.
-            ty::Infer(infer_ty) => {
-                out.push(Component::UnresolvedInferenceVariable(infer_ty));
-            }
-
-            // Most types do not introduce any region binders, nor
-            // involve any other subtle cases, and so the WF relation
-            // simply constraints any regions referenced directly by
-            // the type and then visits the types that are lexically
-            // contained within. (The comments refer to relevant rules
-            // from RFC1214.)
-            ty::Bool |            // OutlivesScalar
-            ty::Char |            // OutlivesScalar
-            ty::Int(..) |         // OutlivesScalar
-            ty::Uint(..) |        // OutlivesScalar
-            ty::Float(..) |       // OutlivesScalar
-            ty::Never |           // ...
-            ty::Adt(..) |         // OutlivesNominalType
-            ty::Foreign(..) |     // OutlivesNominalType
-            ty::Str |             // OutlivesScalar (ish)
-            ty::Slice(..) |       // ...
-            ty::RawPtr(..) |      // ...
-            ty::Ref(..) |         // OutlivesReference
-            ty::Tuple(..) |       // ...
-            ty::FnPtr(_) |        // OutlivesFunction (*)
-            ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*)
-            ty::Bound(..) |
-            ty::Error(_) => {
-                // (*) Function pointers and trait objects are both binders.
-                // In the RFC, this means we would add the bound regions to
-                // the "bound regions list". In our representation, no such
-                // list is maintained explicitly, because bound regions
-                // themselves can be readily identified.
-                compute_components_recursive(tcx, ty.into(), out, visited);
-            }
-        }
-}
-
-/// Collect [Component]s for *all* the args of `parent`.
-///
-/// This should not be used to get the components of `parent` itself.
-/// Use [push_outlives_components] instead.
-pub(super) fn compute_alias_components_recursive<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    alias_ty: Ty<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
-        unreachable!("can only call `compute_alias_components_recursive` on an alias type")
-    };
-    let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
-    for (index, child) in alias_ty.args.iter().enumerate() {
-        if opt_variances.get(index) == Some(&ty::Bivariant) {
-            continue;
-        }
-        if !visited.insert(child) {
-            continue;
-        }
-        match child.unpack() {
-            GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out, visited);
-            }
-            GenericArgKind::Lifetime(lt) => {
-                // Ignore higher ranked regions.
-                if !lt.is_bound() {
-                    out.push(Component::Region(lt));
-                }
-            }
-            GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out, visited);
-            }
-        }
-    }
-}
-
-/// Collect [Component]s for *all* the args of `parent`.
-///
-/// This should not be used to get the components of `parent` itself.
-/// Use [push_outlives_components] instead.
-fn compute_components_recursive<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    parent: GenericArg<'tcx>,
-    out: &mut SmallVec<[Component<'tcx>; 4]>,
-    visited: &mut SsoHashSet<GenericArg<'tcx>>,
-) {
-    for child in parent.walk_shallow(visited) {
-        match child.unpack() {
-            GenericArgKind::Type(ty) => {
-                compute_components(tcx, ty, out, visited);
-            }
-            GenericArgKind::Lifetime(lt) => {
-                // Ignore higher ranked regions.
-                if !lt.is_bound() {
-                    out.push(Component::Region(lt));
-                }
-            }
-            GenericArgKind::Const(_) => {
-                compute_components_recursive(tcx, child, out, visited);
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 48d006e7fbc..89ff4604560 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -8,7 +8,6 @@ use crate::infer::lexical_region_resolve;
 use rustc_middle::traits::query::{NoSolution, OutlivesBound};
 use rustc_middle::ty;
 
-pub mod components;
 pub mod env;
 pub mod for_liveness;
 pub mod obligations;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 32c790523b6..9bb5f775e4a 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -59,7 +59,6 @@
 //! might later infer `?U` to something like `&'b u32`, which would
 //! imply that `'b: 'a`.
 
-use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::outlives::verify::VerifyBoundCx;
 use crate::infer::resolve::OpportunisticRegionResolver;
@@ -75,6 +74,7 @@ use rustc_middle::ty::{
 };
 use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
 use rustc_span::DUMMY_SP;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 use smallvec::smallvec;
 
 use super::env::OutlivesEnvironment;
@@ -291,7 +291,7 @@ where
     fn components_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
-        components: &[Component<'tcx>],
+        components: &[Component<TyCtxt<'tcx>>],
         region: ty::Region<'tcx>,
         category: ConstraintCategory<'tcx>,
     ) {
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 7e977b9b954..ad102dfcc1f 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,10 +1,10 @@
-use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
 use crate::infer::outlives::env::RegionBoundPairs;
 use crate::infer::region_constraints::VerifyIfEq;
 use crate::infer::{GenericKind, VerifyBound};
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_middle::ty::GenericArg;
 use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
+use rustc_type_ir::outlives::{compute_alias_components_recursive, Component};
 
 use smallvec::smallvec;
 
@@ -139,7 +139,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
 
     fn bound_from_components(
         &self,
-        components: &[Component<'tcx>],
+        components: &[Component<TyCtxt<'tcx>>],
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
         let mut bounds = components
@@ -158,7 +158,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
 
     fn bound_from_single_component(
         &self,
-        component: &Component<'tcx>,
+        component: &Component<TyCtxt<'tcx>>,
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
         match *component {
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 0a2e85cc891..c93b89756f9 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -18,11 +18,13 @@
 //! On success, the  LUB/GLB operations return the appropriate bound. The
 //! return value of `Equate` or `Sub` shouldn't really be used.
 
+pub use rustc_next_trait_solver::relate::combine::*;
+
 use super::glb::Glb;
 use super::lub::Lub;
 use super::type_relating::TypeRelating;
+use super::RelateResult;
 use super::StructurallyRelateAliases;
-use super::{RelateResult, TypeRelation};
 use crate::infer::relate;
 use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
 use crate::traits::{Obligation, PredicateObligation};
@@ -32,7 +34,6 @@ use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::Span;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -76,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> {
         b: Ty<'tcx>,
     ) -> RelateResult<'tcx, Ty<'tcx>>
     where
-        R: PredicateEmittingRelation<'tcx>,
+        R: PredicateEmittingRelation<InferCtxt<'tcx>>,
     {
         debug_assert!(!a.has_escaping_bound_vars());
         debug_assert!(!b.has_escaping_bound_vars());
@@ -171,7 +172,7 @@ impl<'tcx> InferCtxt<'tcx> {
         b: ty::Const<'tcx>,
     ) -> RelateResult<'tcx, ty::Const<'tcx>>
     where
-        R: PredicateEmittingRelation<'tcx>,
+        R: PredicateEmittingRelation<InferCtxt<'tcx>>,
     {
         debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
         debug_assert!(!a.has_escaping_bound_vars());
@@ -323,30 +324,3 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         )
     }
 }
-
-pub trait PredicateEmittingRelation<'tcx>: TypeRelation<TyCtxt<'tcx>> {
-    fn span(&self) -> Span;
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx>;
-
-    /// Whether aliases should be related structurally. This is pretty much
-    /// always `No` unless you're equating in some specific locations of the
-    /// new solver. See the comments in these use-cases for more details.
-    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
-
-    /// Register obligations that must hold in order for this relation to hold
-    fn register_goals(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    );
-
-    /// Register predicates that must hold in order for this relation to hold.
-    /// This uses the default `param_env` of the obligation.
-    fn register_predicates(
-        &mut self,
-        obligations: impl IntoIterator<Item: Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
-    );
-
-    /// Register `AliasRelate` obligation(s) that both types must be related to each other.
-    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>);
-}
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index d6e57d85387..fe3b8d60fb9 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -30,7 +30,7 @@ impl<'tcx> InferCtxt<'tcx> {
     /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
     /// other usecases (i.e. setting the value of a type var).
     #[instrument(level = "debug", skip(self, relation))]
-    pub fn instantiate_ty_var<R: PredicateEmittingRelation<'tcx>>(
+    pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
         &self,
         relation: &mut R,
         target_is_expected: bool,
@@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> {
     ///
     /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
     #[instrument(level = "debug", skip(self, relation))]
-    pub(super) fn instantiate_const_var<R: PredicateEmittingRelation<'tcx>>(
+    pub(super) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
         &self,
         relation: &mut R,
         target_is_expected: bool,
diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
index 067004ecaeb..5bb8a113e17 100644
--- a/compiler/rustc_infer/src/infer/relate/glb.rs
+++ b/compiler/rustc_infer/src/infer/relate/glb.rs
@@ -123,7 +123,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
     }
 }
 
-impl<'tcx> PredicateEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
     fn span(&self) -> Span {
         self.fields.trace.span()
     }
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 6cc8d6d910a..46e7466141a 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, Ty};
 ///
 /// GLB moves "down" the lattice (to smaller values); LUB moves
 /// "up" the lattice (to bigger values).
-pub trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation<'tcx> {
+pub trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation<InferCtxt<'tcx>> {
     fn infcx(&self) -> &'f InferCtxt<'tcx>;
 
     fn cause(&self) -> &ObligationCause<'tcx>;
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index 2184416b4cc..94c1464817f 100644
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -123,7 +123,7 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
     }
 }
 
-impl<'tcx> PredicateEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
     fn span(&self) -> Span {
         self.fields.trace.span()
     }
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index 41cc945492d..dd97dc061fe 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -2,11 +2,13 @@
 //! (except for some relations used for diagnostics and heuristics in the compiler).
 //! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc).
 
-pub use rustc_middle::ty::relate::*;
+pub use rustc_middle::ty::relate::RelateResult;
+pub use rustc_next_trait_solver::relate::*;
 
 pub use self::combine::CombineFields;
 pub use self::combine::PredicateEmittingRelation;
 
+#[allow(hidden_glob_reexports)]
 pub(super) mod combine;
 mod generalize;
 mod glb;
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index f2bec9392d5..e206f530519 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -1,7 +1,7 @@
 use super::combine::CombineFields;
 use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
 use crate::infer::BoundRegionConversionTime::HigherRankedType;
-use crate::infer::{DefineOpaqueTypes, SubregionOrigin};
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
 use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::relate::{
     relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
@@ -296,7 +296,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
     }
 }
 
-impl<'tcx> PredicateEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
     fn span(&self) -> Span {
         self.fields.trace.span()
     }
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 24cf9f03fcd..b269bfcbfeb 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,11 +1,12 @@
 use smallvec::smallvec;
 
-use crate::infer::outlives::components::{push_outlives_components, Component};
 use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
 use rustc_data_structures::fx::FxHashSet;
+use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 
 pub fn anonymize_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -82,7 +83,6 @@ pub struct Elaborator<'tcx, O> {
 enum Filter {
     All,
     OnlySelf,
-    OnlySelfThatDefines(Ident),
 }
 
 /// Describes how to elaborate an obligation into a sub-obligation.
@@ -252,12 +252,6 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
         self
     }
 
-    /// Filter to only the supertraits of trait predicates that define the assoc_ty.
-    pub fn filter_only_self_that_defines(mut self, assoc_ty: Ident) -> Self {
-        self.mode = Filter::OnlySelfThatDefines(assoc_ty);
-        self
-    }
-
     fn elaborate(&mut self, elaboratable: &O) {
         let tcx = self.visited.tcx;
 
@@ -277,9 +271,6 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
                 let predicates = match self.mode {
                     Filter::All => tcx.explicit_implied_predicates_of(data.def_id()),
                     Filter::OnlySelf => tcx.explicit_super_predicates_of(data.def_id()),
-                    Filter::OnlySelfThatDefines(ident) => {
-                        tcx.explicit_supertraits_containing_assoc_item((data.def_id(), ident))
-                    }
                 };
 
                 let obligations =
@@ -405,14 +396,14 @@ impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> {
 pub fn supertraits<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
-) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> {
+) -> FilterToTraits<Elaborator<'tcx, ty::Clause<'tcx>>> {
     elaborate(tcx, [trait_ref.upcast(tcx)]).filter_only_self().filter_to_traits()
 }
 
 pub fn transitive_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> {
+) -> FilterToTraits<Elaborator<'tcx, ty::Clause<'tcx>>> {
     elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx)))
         .filter_only_self()
         .filter_to_traits()
@@ -427,17 +418,37 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
     assoc_name: Ident,
-) -> FilterToTraits<Elaborator<'tcx, ty::Predicate<'tcx>>> {
-    elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.upcast(tcx)))
-        .filter_only_self_that_defines(assoc_name)
-        .filter_to_traits()
+) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
+    let mut seen = FxHashSet::default();
+    let mut stack: Vec<_> = trait_refs.collect();
+
+    std::iter::from_fn(move || {
+        while let Some(trait_ref) = stack.pop() {
+            if !seen.insert(tcx.anonymize_bound_vars(trait_ref)) {
+                continue;
+            }
+
+            stack.extend(
+                tcx.explicit_supertraits_containing_assoc_item((trait_ref.def_id(), assoc_name))
+                    .instantiate_own_identity()
+                    .map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref))
+                    .filter_map(|clause| clause.as_trait_clause())
+                    // FIXME: Negative supertraits are elaborated here lol
+                    .map(|trait_pred| trait_pred.to_poly_trait_ref()),
+            );
+
+            return Some(trait_ref);
+        }
+
+        None
+    })
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Other
 ///////////////////////////////////////////////////////////////////////////
 
-impl<'tcx> Elaborator<'tcx, ty::Predicate<'tcx>> {
+impl<'tcx> Elaborator<'tcx, ty::Clause<'tcx>> {
     fn filter_to_traits(self) -> FilterToTraits<Self> {
         FilterToTraits { base_iterator: self }
     }
@@ -449,7 +460,7 @@ pub struct FilterToTraits<I> {
     base_iterator: I,
 }
 
-impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+impl<'tcx, I: Iterator<Item = ty::Clause<'tcx>>> Iterator for FilterToTraits<I> {
     type Item = ty::PolyTraitRef<'tcx>;
 
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 2ade6964ca8..048c2fb4e67 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4189,6 +4189,7 @@ declare_lint! {
         reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
         reference: "issue #123748 <https://github.com/rust-lang/rust/issues/123748>",
     };
+    @edition Edition2024 => Deny;
     report_in_external_macro
 }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 305ba1ef3bb..2f3a6ee601b 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -31,9 +31,18 @@ pub struct Map<'hir> {
 
 /// An iterator that walks up the ancestor tree of a given `HirId`.
 /// Constructed using `tcx.hir().parent_iter(hir_id)`.
-pub struct ParentHirIterator<'hir> {
+struct ParentHirIterator<'hir> {
     current_id: HirId,
     map: Map<'hir>,
+    // Cache the current value of `hir_owner_nodes` to avoid repeatedly calling the same query for
+    // the same owner, which will uselessly record many times the same query dependency.
+    current_owner_nodes: Option<&'hir OwnerNodes<'hir>>,
+}
+
+impl<'hir> ParentHirIterator<'hir> {
+    fn new(map: Map<'hir>, current_id: HirId) -> ParentHirIterator<'hir> {
+        ParentHirIterator { current_id, map, current_owner_nodes: None }
+    }
 }
 
 impl<'hir> Iterator for ParentHirIterator<'hir> {
@@ -44,13 +53,22 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
             return None;
         }
 
-        // There are nodes that do not have entries, so we need to skip them.
-        let parent_id = self.map.tcx.parent_hir_id(self.current_id);
+        let HirId { owner, local_id } = self.current_id;
 
-        if parent_id == self.current_id {
-            self.current_id = CRATE_HIR_ID;
-            return None;
-        }
+        let parent_id = if local_id == ItemLocalId::ZERO {
+            // We go from an owner to its parent, so clear the cache.
+            self.current_owner_nodes = None;
+            self.map.tcx.hir_owner_parent(owner)
+        } else {
+            let owner_nodes =
+                self.current_owner_nodes.get_or_insert_with(|| self.map.tcx.hir_owner_nodes(owner));
+            let parent_local_id = owner_nodes.nodes[local_id].parent;
+            // HIR indexing should have checked that.
+            debug_assert_ne!(parent_local_id, local_id);
+            HirId { owner, local_id: parent_local_id }
+        };
+
+        debug_assert_ne!(parent_id, self.current_id);
 
         self.current_id = parent_id;
         return Some(parent_id);
@@ -479,7 +497,7 @@ impl<'hir> Map<'hir> {
     /// until the crate root is reached. Prefer this over your own loop using `parent_id`.
     #[inline]
     pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir {
-        ParentHirIterator { current_id, map: self }
+        ParentHirIterator::new(self, current_id)
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index bf834ef7607..98f35b6b8ab 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -54,6 +54,13 @@ pub struct Expr<'tcx> {
     pub kind: ExprKind,
     args: ty::GenericArgsRef<'tcx>,
 }
+
+impl<'tcx> rustc_type_ir::inherent::ExprConst<TyCtxt<'tcx>> for Expr<'tcx> {
+    fn args(self) -> ty::GenericArgsRef<'tcx> {
+        self.args
+    }
+}
+
 impl<'tcx> Expr<'tcx> {
     pub fn new_binop(
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 055749ba3a3..dca48069974 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -92,6 +92,8 @@ use std::ops::{Bound, Deref};
 impl<'tcx> Interner for TyCtxt<'tcx> {
     type DefId = DefId;
     type LocalDefId = LocalDefId;
+    type Span = Span;
+
     type GenericArgs = ty::GenericArgsRef<'tcx>;
 
     type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>];
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index b169d672a84..ebf0d7ed737 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -10,18 +10,6 @@ use crate::ty::{self as ty, Ty, TyCtxt};
 
 pub type RelateResult<'tcx, T> = rustc_type_ir::relate::RelateResult<TyCtxt<'tcx>, T>;
 
-/// Whether aliases should be related structurally or not. Used
-/// to adjust the behavior of generalization and combine.
-///
-/// This should always be `No` unless in a few special-cases when
-/// instantiating canonical responses and in the new solver. Each
-/// such case should have a comment explaining why it is used.
-#[derive(Debug, Copy, Clone)]
-pub enum StructurallyRelateAliases {
-    Yes,
-    No,
-}
-
 impl<'tcx> Relate<TyCtxt<'tcx>> for ty::ImplSubject<'tcx> {
     #[inline]
     fn relate<R: TypeRelation<TyCtxt<'tcx>>>(
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index e0f204a687f..efcaf89081f 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -78,23 +78,6 @@ impl<'tcx> GenericArg<'tcx> {
     pub fn walk(self) -> TypeWalker<'tcx> {
         TypeWalker::new(self)
     }
-
-    /// Iterator that walks the immediate children of `self`. Hence
-    /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
-    /// (but not `i32`, like `walk`).
-    ///
-    /// Iterator only walks items once.
-    /// It accepts visited set, updates it with all visited types
-    /// and skips any types that are already there.
-    pub fn walk_shallow(
-        self,
-        visited: &mut SsoHashSet<GenericArg<'tcx>>,
-    ) -> impl Iterator<Item = GenericArg<'tcx>> {
-        let mut stack = SmallVec::new();
-        push_inner(&mut stack, self);
-        stack.retain(|a| visited.insert(*a));
-        stack.into_iter()
-    }
 }
 
 impl<'tcx> Ty<'tcx> {
diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs
index a6a9c01faaa..761475d3d6b 100644
--- a/compiler/rustc_next_trait_solver/src/lib.rs
+++ b/compiler/rustc_next_trait_solver/src/lib.rs
@@ -6,5 +6,6 @@
 
 pub mod canonicalizer;
 pub mod delegate;
+pub mod relate;
 pub mod resolve;
 pub mod solve;
diff --git a/compiler/rustc_next_trait_solver/src/relate.rs b/compiler/rustc_next_trait_solver/src/relate.rs
new file mode 100644
index 00000000000..db819961bbd
--- /dev/null
+++ b/compiler/rustc_next_trait_solver/src/relate.rs
@@ -0,0 +1,15 @@
+pub use rustc_type_ir::relate::*;
+
+pub mod combine;
+
+/// Whether aliases should be related structurally or not. Used
+/// to adjust the behavior of generalization and combine.
+///
+/// This should always be `No` unless in a few special-cases when
+/// instantiating canonical responses and in the new solver. Each
+/// such case should have a comment explaining why it is used.
+#[derive(Debug, Copy, Clone)]
+pub enum StructurallyRelateAliases {
+    Yes,
+    No,
+}
diff --git a/compiler/rustc_next_trait_solver/src/relate/combine.rs b/compiler/rustc_next_trait_solver/src/relate/combine.rs
new file mode 100644
index 00000000000..96968327d8e
--- /dev/null
+++ b/compiler/rustc_next_trait_solver/src/relate/combine.rs
@@ -0,0 +1,34 @@
+pub use rustc_type_ir::relate::*;
+use rustc_type_ir::solve::Goal;
+use rustc_type_ir::{InferCtxtLike, Interner, Upcast};
+
+use super::StructurallyRelateAliases;
+
+pub trait PredicateEmittingRelation<Infcx, I = <Infcx as InferCtxtLike>::Interner>:
+    TypeRelation<I>
+where
+    Infcx: InferCtxtLike<Interner = I>,
+    I: Interner,
+{
+    fn span(&self) -> I::Span;
+
+    fn param_env(&self) -> I::ParamEnv;
+
+    /// Whether aliases should be related structurally. This is pretty much
+    /// always `No` unless you're equating in some specific locations of the
+    /// new solver. See the comments in these use-cases for more details.
+    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases;
+
+    /// Register obligations that must hold in order for this relation to hold
+    fn register_goals(&mut self, obligations: impl IntoIterator<Item = Goal<I, I::Predicate>>);
+
+    /// Register predicates that must hold in order for this relation to hold.
+    /// This uses the default `param_env` of the obligation.
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item: Upcast<I, I::Predicate>>,
+    );
+
+    /// Register `AliasRelate` obligation(s) that both types must be related to each other.
+    fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
+}
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 58fef9b6c45..a8fe35f45b3 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -282,7 +282,7 @@ impl<'a> Parser<'a> {
     pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
         let mut attrs = ast::AttrVec::new();
         loop {
-            let start_pos: u32 = self.num_bump_calls.try_into().unwrap();
+            let start_pos = self.num_bump_calls;
             // Only try to parse if it is an inner attribute (has `!`).
             let attr = if self.check(&token::Pound) && self.look_ahead(1, |t| t == &token::Not) {
                 Some(self.parse_attribute(InnerAttrPolicy::Permitted)?)
@@ -303,7 +303,7 @@ impl<'a> Parser<'a> {
                 None
             };
             if let Some(attr) = attr {
-                let end_pos: u32 = self.num_bump_calls.try_into().unwrap();
+                let end_pos = self.num_bump_calls;
                 // If we are currently capturing tokens, mark the location of this inner attribute.
                 // If capturing ends up creating a `LazyAttrTokenStream`, we will include
                 // this replace range with it, removing the inner attribute from the final
@@ -313,7 +313,7 @@ impl<'a> Parser<'a> {
                 // corresponding macro).
                 let range = start_pos..end_pos;
                 if let Capturing::Yes = self.capture_state.capturing {
-                    self.capture_state.inner_attr_ranges.insert(attr.id, (range, vec![]));
+                    self.capture_state.inner_attr_ranges.insert(attr.id, (range, None));
                 }
                 attrs.push(attr);
             } else {
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 13a647adfe3..38f18022e3c 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,6 +1,6 @@
 use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken};
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttributesData, DelimSpacing};
+use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing};
 use rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, ToAttrTokenStream};
 use rustc_ast::{self as ast};
 use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens};
@@ -8,7 +8,6 @@ use rustc_errors::PResult;
 use rustc_session::parse::ParseSess;
 use rustc_span::{sym, Span, DUMMY_SP};
 
-use std::ops::Range;
 use std::{iter, mem};
 
 /// A wrapper type to ensure that the parser handles outer attributes correctly.
@@ -88,7 +87,6 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
 //
 // This also makes `Parser` very cheap to clone, since
 // there is no intermediate collection buffer to clone.
-#[derive(Clone)]
 struct LazyAttrTokenStreamImpl {
     start_token: (Token, Spacing),
     cursor_snapshot: TokenCursor,
@@ -146,24 +144,23 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
             // start position, we ensure that any replace range which encloses
             // another replace range will capture the *replaced* tokens for the inner
             // range, not the original tokens.
-            for (range, new_tokens) in replace_ranges.into_iter().rev() {
+            for (range, target) in replace_ranges.into_iter().rev() {
                 assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}");
-                // Replace ranges are only allowed to decrease the number of tokens.
-                assert!(
-                    range.len() >= new_tokens.len(),
-                    "Range {range:?} has greater len than {new_tokens:?}"
-                );
-
-                // Replace any removed tokens with `FlatToken::Empty`.
-                // This keeps the total length of `tokens` constant throughout the
-                // replacement process, allowing us to use all of the `ReplaceRanges` entries
-                // without adjusting indices.
-                let filler = iter::repeat((FlatToken::Empty, Spacing::Alone))
-                    .take(range.len() - new_tokens.len());
 
+                // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus
+                // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the
+                // total length of `tokens` constant throughout the replacement process, allowing
+                // us to use all of the `ReplaceRanges` entries without adjusting indices.
+                let target_len = target.is_some() as usize;
                 tokens.splice(
                     (range.start as usize)..(range.end as usize),
-                    new_tokens.into_iter().chain(filler),
+                    target
+                        .into_iter()
+                        .map(|target| (FlatToken::AttrsTarget(target), Spacing::Alone))
+                        .chain(
+                            iter::repeat((FlatToken::Empty, Spacing::Alone))
+                                .take(range.len() - target_len),
+                        ),
                 );
             }
             make_attr_token_stream(tokens.into_iter(), self.break_last_token)
@@ -316,7 +313,7 @@ impl<'a> Parser<'a> {
                 .iter()
                 .cloned()
                 .chain(inner_attr_replace_ranges.iter().cloned())
-                .map(|(range, tokens)| ((range.start - start_pos)..(range.end - start_pos), tokens))
+                .map(|(range, data)| ((range.start - start_pos)..(range.end - start_pos), data))
                 .collect()
         };
 
@@ -346,18 +343,14 @@ impl<'a> Parser<'a> {
             && matches!(self.capture_state.capturing, Capturing::Yes)
             && has_cfg_or_cfg_attr(final_attrs)
         {
-            let attr_data = AttributesData { attrs: final_attrs.iter().cloned().collect(), tokens };
+            assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
 
-            // Replace the entire AST node that we just parsed, including attributes,
-            // with a `FlatToken::AttrTarget`. If this AST node is inside an item
-            // that has `#[derive]`, then this will allow us to cfg-expand this
-            // AST node.
+            // Replace the entire AST node that we just parsed, including attributes, with
+            // `target`. If this AST node is inside an item that has `#[derive]`, then this will
+            // allow us to cfg-expand this AST node.
             let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos };
-            let new_tokens = vec![(FlatToken::AttrTarget(attr_data), Spacing::Alone)];
-
-            assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
-            let range: Range<u32> = (start_pos.try_into().unwrap())..(end_pos.try_into().unwrap());
-            self.capture_state.replace_ranges.push((range, new_tokens));
+            let target = AttrsTarget { attrs: final_attrs.iter().cloned().collect(), tokens };
+            self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target)));
             self.capture_state.replace_ranges.extend(inner_attr_replace_ranges);
         }
 
@@ -419,11 +412,11 @@ fn make_attr_token_stream(
                 .expect("Bottom token frame is missing!")
                 .inner
                 .push(AttrTokenTree::Token(token, spacing)),
-            FlatToken::AttrTarget(data) => stack
+            FlatToken::AttrsTarget(target) => stack
                 .last_mut()
                 .expect("Bottom token frame is missing!")
                 .inner
-                .push(AttrTokenTree::Attributes(data)),
+                .push(AttrTokenTree::AttrsTarget(target)),
             FlatToken::Empty => {}
         }
         token_and_spacing = iter.next();
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 5f16a3e1f37..45ca267fe5d 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -20,7 +20,7 @@ use path::PathStyle;
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
+use rustc_ast::tokenstream::{AttrsTarget, DelimSpacing, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
@@ -203,13 +203,13 @@ struct ClosureSpans {
 }
 
 /// Indicates a range of tokens that should be replaced by
-/// the tokens in the provided vector. This is used in two
+/// the tokens in the provided `AttrsTarget`. This is used in two
 /// places during token collection:
 ///
 /// 1. During the parsing of an AST node that may have a `#[derive]`
 /// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]`
 /// In this case, we use a `ReplaceRange` to replace the entire inner AST node
-/// with `FlatToken::AttrTarget`, allowing us to perform eager cfg-expansion
+/// with `FlatToken::AttrsTarget`, allowing us to perform eager cfg-expansion
 /// on an `AttrTokenStream`.
 ///
 /// 2. When we parse an inner attribute while collecting tokens. We
@@ -219,7 +219,7 @@ struct ClosureSpans {
 /// the first macro inner attribute to invoke a proc-macro).
 /// When create a `TokenStream`, the inner attributes get inserted
 /// into the proper place in the token stream.
-type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
+type ReplaceRange = (Range<u32>, Option<AttrsTarget>);
 
 /// Controls how we capture tokens. Capturing can be expensive,
 /// so we try to avoid performing capturing in cases where
@@ -1608,11 +1608,10 @@ enum FlatToken {
     /// A token - this holds both delimiter (e.g. '{' and '}')
     /// and non-delimiter tokens
     Token(Token),
-    /// Holds the `AttributesData` for an AST node. The
-    /// `AttributesData` is inserted directly into the
-    /// constructed `AttrTokenStream` as
-    /// an `AttrTokenTree::Attributes`.
-    AttrTarget(AttributesData),
+    /// Holds the `AttrsTarget` for an AST node. The `AttrsTarget` is inserted
+    /// directly into the constructed `AttrTokenStream` as an
+    /// `AttrTokenTree::AttrsTarget`.
+    AttrsTarget(AttrsTarget),
     /// A special 'empty' token that is ignored during the conversion
     /// to an `AttrTokenStream`. This is used to simplify the
     /// handling of replace ranges.
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 80619c59cc3..a4fdb4a0baf 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -8,6 +8,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_span::hygiene::LocalExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
+use std::mem;
 use tracing::debug;
 
 pub(crate) fn collect_definitions(
@@ -15,8 +16,9 @@ pub(crate) fn collect_definitions(
     fragment: &AstFragment,
     expansion: LocalExpnId,
 ) {
-    let (parent_def, impl_trait_context) = resolver.invocation_parents[&expansion];
-    fragment.visit_with(&mut DefCollector { resolver, parent_def, expansion, impl_trait_context });
+    let (parent_def, impl_trait_context, in_attr) = resolver.invocation_parents[&expansion];
+    let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
+    fragment.visit_with(&mut visitor);
 }
 
 /// Creates `DefId`s for nodes in the AST.
@@ -24,6 +26,7 @@ struct DefCollector<'a, 'b, 'tcx> {
     resolver: &'a mut Resolver<'b, 'tcx>,
     parent_def: LocalDefId,
     impl_trait_context: ImplTraitContext,
+    in_attr: bool,
     expansion: LocalExpnId,
 }
 
@@ -53,7 +56,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
-        let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
+        let orig_parent_def = mem::replace(&mut self.parent_def, parent_def);
         f(self);
         self.parent_def = orig_parent_def;
     }
@@ -63,7 +66,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
         impl_trait_context: ImplTraitContext,
         f: F,
     ) {
-        let orig_itc = std::mem::replace(&mut self.impl_trait_context, impl_trait_context);
+        let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context);
         f(self);
         self.impl_trait_context = orig_itc;
     }
@@ -105,8 +108,10 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
 
     fn visit_macro_invoc(&mut self, id: NodeId) {
         let id = id.placeholder_to_expn_id();
-        let old_parent =
-            self.resolver.invocation_parents.insert(id, (self.parent_def, self.impl_trait_context));
+        let old_parent = self
+            .resolver
+            .invocation_parents
+            .insert(id, (self.parent_def, self.impl_trait_context, self.in_attr));
         assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
     }
 }
@@ -413,4 +418,10 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
             visit::walk_crate(self, krate)
         }
     }
+
+    fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result {
+        let orig_in_attr = mem::replace(&mut self.in_attr, true);
+        visit::walk_attribute(self, attr);
+        self.in_attr = orig_in_attr;
+    }
 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ad4e222f4de..1d37264f96a 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1744,7 +1744,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                             ) {
                                 self.r.dcx().emit_err(errors::LendingIteratorReportError {
                                     lifetime: lifetime.ident.span,
-                                    ty: ty.span(),
+                                    ty: ty.span,
                                 });
                             } else {
                                 self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 7bf32a023f1..7cb5a3fb2fd 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1139,7 +1139,7 @@ pub struct Resolver<'a, 'tcx> {
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
     /// we know what parent node that fragment should be attached to thanks to this table,
     /// and how the `impl Trait` fragments were introduced.
-    invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext)>,
+    invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext, bool /*in_attr*/)>,
 
     /// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
     /// FIXME: Replace with a more general AST map (together with some other fields).
@@ -1371,7 +1371,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed);
 
         let mut invocation_parents = FxHashMap::default();
-        invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
+        invocation_parents
+            .insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential, false));
 
         let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx
             .sess
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 026a2ca1412..cb9bebd33d3 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -297,11 +297,12 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
             .invocation_parents
             .get(&invoc_id)
             .or_else(|| self.invocation_parents.get(&eager_expansion_root))
-            .map(|&(mod_def_id, _)| mod_def_id)
-            .filter(|&mod_def_id| {
-                invoc.fragment_kind == AstFragmentKind::Expr
+            .filter(|&&(mod_def_id, _, in_attr)| {
+                in_attr
+                    && invoc.fragment_kind == AstFragmentKind::Expr
                     && self.tcx.def_kind(mod_def_id) == DefKind::Mod
-            });
+            })
+            .map(|&(mod_def_id, ..)| mod_def_id);
         let (ext, res) = self.smart_resolve_macro_path(
             path,
             kind,
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index c95649e2ffb..ad087620ae0 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,3 +1,4 @@
+use crate::infer::at::ToTrace;
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
 
@@ -17,6 +18,16 @@ pub use rustc_infer::infer::*;
 
 #[extension(pub trait InferCtxtExt<'tcx>)]
 impl<'tcx> InferCtxt<'tcx> {
+    fn can_eq<T: ToTrace<'tcx>>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool {
+        self.probe(|_| {
+            let ocx = ObligationCtxt::new(self);
+            let Ok(()) = ocx.eq(&ObligationCause::dummy(), param_env, a, b) else {
+                return false;
+            };
+            ocx.select_where_possible().is_empty()
+        })
+    }
+
     fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let ty = self.resolve_vars_if_possible(ty);
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 32c8a454b40..94b28426f43 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -1,5 +1,10 @@
 use super::{ObligationCauseCode, PredicateObligation};
+use crate::errors::{
+    EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
+};
 use crate::infer::error_reporting::TypeErrCtxt;
+use crate::infer::InferCtxtExt;
+use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
 use rustc_ast::AttrArgs;
 use rustc_ast::AttrArgsEq;
 use rustc_ast::AttrKind;
@@ -21,12 +26,6 @@ use rustc_span::Span;
 use std::iter;
 use std::path::PathBuf;
 
-use crate::errors::{
-    EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
-};
-
-use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
-
 /// The symbols which are always allowed in a format string
 static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
     kw::SelfUpper,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index a0a8e5963f1..52edffce614 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3472,6 +3472,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     )
                 });
             }
+            // Suppress `compare_type_predicate_entailment` errors for RPITITs, since they
+            // should be implied by the parent method.
+            ObligationCauseCode::CompareImplItem { trait_item_def_id, .. }
+                if tcx.is_impl_trait_in_trait(trait_item_def_id) => {}
             ObligationCauseCode::CompareImplItem { trait_item_def_id, kind, .. } => {
                 let item_name = tcx.item_name(trait_item_def_id);
                 let msg = format!(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 17b6dd2bc58..5461f9e65af 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -1073,7 +1073,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             // mismatched, then we have a totally different error to report.
             if self.enter_forall(found_args, |found_args| {
                 self.enter_forall(expected_args, |expected_args| {
-                    !self.can_sub(obligation.param_env, expected_args, found_args)
+                    !self.can_eq(obligation.param_env, expected_args, found_args)
                 })
             }) {
                 return None;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index b38841db923..8525215a3bc 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -3,7 +3,6 @@ use crate::traits::wf;
 use crate::traits::ObligationCtxt;
 
 use rustc_infer::infer::canonical::Canonical;
-use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
 use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
@@ -12,6 +11,7 @@ use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::DUMMY_SP;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
 use smallvec::{smallvec, SmallVec};
 
 #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
@@ -284,7 +284,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
 /// those relationships.
 fn implied_bounds_from_components<'tcx>(
     sub_region: ty::Region<'tcx>,
-    sup_components: SmallVec<[Component<'tcx>; 4]>,
+    sup_components: SmallVec<[Component<TyCtxt<'tcx>>; 4]>,
 ) -> Vec<OutlivesBound<'tcx>> {
     sup_components
         .into_iter()
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 68cc04bc8e6..fa130420174 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -18,7 +18,7 @@ use super::{
     TraitQueryMode,
 };
 
-use crate::infer::{InferCtxt, InferOk, TypeFreshener};
+use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
 use crate::solve::InferCtxtSelectExt as _;
 use crate::traits::error_reporting::TypeErrCtxtExt;
 use crate::traits::normalize::normalize_with_depth;
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index ffe16964ae5..68c2575258d 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -232,6 +232,10 @@ pub trait Region<I: Interner<Region = Self>>:
     fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
 
     fn new_static(interner: I) -> Self;
+
+    fn is_bound(self) -> bool {
+        matches!(self.kind(), ty::ReBound(..))
+    }
 }
 
 pub trait Const<I: Interner<Const = Self>>:
@@ -272,6 +276,10 @@ pub trait Const<I: Interner<Const = Self>>:
     }
 }
 
+pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
+    fn args(self) -> I::GenericArgs;
+}
+
 pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
     fn count(&self) -> usize;
 }
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index db97bdca382..6e013768c3e 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -32,6 +32,7 @@ pub trait Interner:
 {
     type DefId: DefId<Self>;
     type LocalDefId: Copy + Debug + Hash + Eq + Into<Self::DefId> + TypeFoldable<Self>;
+    type Span: Copy + Debug + Hash + Eq;
 
     type GenericArgs: GenericArgs<Self>;
     type GenericArgsSlice: Copy + Debug + Hash + Eq + SliceLike<Item = Self::GenericArg>;
@@ -109,7 +110,7 @@ pub trait Interner:
     type ParamConst: Copy + Debug + Hash + Eq + ParamLike;
     type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
     type ValueConst: Copy + Debug + Hash + Eq;
-    type ExprConst: Copy + Debug + Hash + Eq + Relate<Self>;
+    type ExprConst: ExprConst<Self>;
 
     // Kinds of regions
     type Region: Region<Self>;
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index c57ac74cdfd..2a909b06baf 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -27,6 +27,7 @@ pub mod inherent;
 pub mod ir_print;
 pub mod lang_items;
 pub mod lift;
+pub mod outlives;
 pub mod relate;
 pub mod solve;
 
diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs
new file mode 100644
index 00000000000..61dfa2643d8
--- /dev/null
+++ b/compiler/rustc_type_ir/src/outlives.rs
@@ -0,0 +1,335 @@
+//! The outlives relation `T: 'a` or `'a: 'b`. This code frequently
+//! refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
+//! RFC for reference.
+
+use smallvec::{smallvec, SmallVec};
+use tracing::debug;
+
+use crate::data_structures::SsoHashSet;
+use crate::inherent::*;
+use crate::visit::TypeVisitableExt as _;
+use crate::{self as ty, Interner};
+
+#[derive(derivative::Derivative)]
+#[derivative(Debug(bound = ""))]
+pub enum Component<I: Interner> {
+    Region(I::Region),
+    Param(I::ParamTy),
+    Placeholder(I::PlaceholderTy),
+    UnresolvedInferenceVariable(ty::InferTy),
+
+    // Projections like `T::Foo` are tricky because a constraint like
+    // `T::Foo: 'a` can be satisfied in so many ways. There may be a
+    // where-clause that says `T::Foo: 'a`, or the defining trait may
+    // include a bound like `type Foo: 'static`, or -- in the most
+    // conservative way -- we can prove that `T: 'a` (more generally,
+    // that all components in the projection outlive `'a`). This code
+    // is not in a position to judge which is the best technique, so
+    // we just product the projection as a component and leave it to
+    // the consumer to decide (but see `EscapingProjection` below).
+    Alias(ty::AliasTy<I>),
+
+    // In the case where a projection has escaping regions -- meaning
+    // regions bound within the type itself -- we always use
+    // the most conservative rule, which requires that all components
+    // outlive the bound. So for example if we had a type like this:
+    //
+    //     for<'a> Trait1<  <T as Trait2<'a,'b>>::Foo  >
+    //                      ~~~~~~~~~~~~~~~~~~~~~~~~~
+    //
+    // then the inner projection (underlined) has an escaping region
+    // `'a`. We consider that outer trait `'c` to meet a bound if `'b`
+    // outlives `'b: 'c`, and we don't consider whether the trait
+    // declares that `Foo: 'static` etc. Therefore, we just return the
+    // free components of such a projection (in this case, `'b`).
+    //
+    // However, in the future, we may want to get smarter, and
+    // actually return a "higher-ranked projection" here. Therefore,
+    // we mark that these components are part of an escaping
+    // projection, so that implied bounds code can avoid relying on
+    // them. This gives us room to improve the regionck reasoning in
+    // the future without breaking backwards compat.
+    EscapingAlias(Vec<Component<I>>),
+}
+
+/// Push onto `out` all the things that must outlive `'a` for the condition
+/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
+pub fn push_outlives_components<I: Interner>(
+    tcx: I,
+    ty0: I::Ty,
+    out: &mut SmallVec<[Component<I>; 4]>,
+) {
+    let mut visited = SsoHashSet::new();
+    compute_components_for_ty(tcx, ty0, out, &mut visited);
+    debug!("components({:?}) = {:?}", ty0, out);
+}
+
+fn compute_components_for_arg<I: Interner>(
+    tcx: I,
+    arg: I::GenericArg,
+    out: &mut SmallVec<[Component<I>; 4]>,
+    visited: &mut SsoHashSet<I::GenericArg>,
+) {
+    match arg.kind() {
+        ty::GenericArgKind::Type(ty) => {
+            compute_components_for_ty(tcx, ty, out, visited);
+        }
+        ty::GenericArgKind::Lifetime(lt) => {
+            compute_components_for_lt(lt, out);
+        }
+        ty::GenericArgKind::Const(ct) => {
+            compute_components_for_const(tcx, ct, out, visited);
+        }
+    }
+}
+
+fn compute_components_for_ty<I: Interner>(
+    tcx: I,
+    ty: I::Ty,
+    out: &mut SmallVec<[Component<I>; 4]>,
+    visited: &mut SsoHashSet<I::GenericArg>,
+) {
+    if !visited.insert(ty.into()) {
+        return;
+    }
+    // Descend through the types, looking for the various "base"
+    // components and collecting them into `out`. This is not written
+    // with `collect()` because of the need to sometimes skip subtrees
+    // in the `subtys` iterator (e.g., when encountering a
+    // projection).
+    match ty.kind() {
+        ty::FnDef(_, args) => {
+            // HACK(eddyb) ignore lifetimes found shallowly in `args`.
+            // This is inconsistent with `ty::Adt` (including all args)
+            // and with `ty::Closure` (ignoring all args other than
+            // upvars, of which a `ty::FnDef` doesn't have any), but
+            // consistent with previous (accidental) behavior.
+            // See https://github.com/rust-lang/rust/issues/70917
+            // for further background and discussion.
+            for child in args.iter() {
+                match child.kind() {
+                    ty::GenericArgKind::Type(ty) => {
+                        compute_components_for_ty(tcx, ty, out, visited);
+                    }
+                    ty::GenericArgKind::Lifetime(_) => {}
+                    ty::GenericArgKind::Const(ct) => {
+                        compute_components_for_const(tcx, ct, out, visited);
+                    }
+                }
+            }
+        }
+
+        ty::Pat(element, _) | ty::Array(element, _) => {
+            compute_components_for_ty(tcx, element, out, visited);
+        }
+
+        ty::Closure(_, args) => {
+            let tupled_ty = args.as_closure().tupled_upvars_ty();
+            compute_components_for_ty(tcx, tupled_ty, out, visited);
+        }
+
+        ty::CoroutineClosure(_, args) => {
+            let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty();
+            compute_components_for_ty(tcx, tupled_ty, out, visited);
+        }
+
+        ty::Coroutine(_, args) => {
+            // Same as the closure case
+            let tupled_ty = args.as_coroutine().tupled_upvars_ty();
+            compute_components_for_ty(tcx, tupled_ty, out, visited);
+
+            // We ignore regions in the coroutine interior as we don't
+            // want these to affect region inference
+        }
+
+        // All regions are bound inside a witness, and we don't emit
+        // higher-ranked outlives components currently.
+        ty::CoroutineWitness(..) => {},
+
+        // OutlivesTypeParameterEnv -- the actual checking that `X:'a`
+        // is implied by the environment is done in regionck.
+        ty::Param(p) => {
+            out.push(Component::Param(p));
+        }
+
+        ty::Placeholder(p) => {
+            out.push(Component::Placeholder(p));
+        }
+
+        // For projections, we prefer to generate an obligation like
+        // `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
+        // regionck more ways to prove that it holds. However,
+        // regionck is not (at least currently) prepared to deal with
+        // higher-ranked regions that may appear in the
+        // trait-ref. Therefore, if we see any higher-ranked regions,
+        // we simply fallback to the most restrictive rule, which
+        // requires that `Pi: 'a` for all `i`.
+        ty::Alias(_, alias_ty) => {
+            if !alias_ty.has_escaping_bound_vars() {
+                // best case: no escaping regions, so push the
+                // projection and skip the subtree (thus generating no
+                // constraints for Pi). This defers the choice between
+                // the rules OutlivesProjectionEnv,
+                // OutlivesProjectionTraitDef, and
+                // OutlivesProjectionComponents to regionck.
+                out.push(Component::Alias(alias_ty));
+            } else {
+                // fallback case: hard code
+                // OutlivesProjectionComponents. Continue walking
+                // through and constrain Pi.
+                let mut subcomponents = smallvec![];
+                let mut subvisited = SsoHashSet::new();
+                compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
+                out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
+            }
+        }
+
+        // We assume that inference variables are fully resolved.
+        // So, if we encounter an inference variable, just record
+        // the unresolved variable as a component.
+        ty::Infer(infer_ty) => {
+            out.push(Component::UnresolvedInferenceVariable(infer_ty));
+        }
+
+        // Most types do not introduce any region binders, nor
+        // involve any other subtle cases, and so the WF relation
+        // simply constraints any regions referenced directly by
+        // the type and then visits the types that are lexically
+        // contained within. (The comments refer to relevant rules
+        // from RFC1214.)
+
+        ty::Bool |            // OutlivesScalar
+        ty::Char |            // OutlivesScalar
+        ty::Int(..) |         // OutlivesScalar
+        ty::Uint(..) |        // OutlivesScalar
+        ty::Float(..) |       // OutlivesScalar
+        ty::Never |           // OutlivesScalar
+        ty::Foreign(..) |     // OutlivesNominalType
+        ty::Str |             // OutlivesScalar (ish)
+        ty::Bound(..) |
+        ty::Error(_) => {
+            // Trivial.
+        }
+
+        // OutlivesNominalType
+        ty::Adt(_, args) => {
+            for arg in args.iter() {
+                compute_components_for_arg(tcx, arg, out, visited);
+            }
+        }
+
+        // OutlivesNominalType
+        ty::Slice(ty) |
+        ty::RawPtr(ty, _) => {
+            compute_components_for_ty(tcx, ty, out, visited);
+        }
+        ty::Tuple(tys) => {
+            for ty in tys.iter() {
+                compute_components_for_ty(tcx, ty, out, visited);
+            }
+        }
+
+        // OutlivesReference
+        ty::Ref(lt, ty, _) => {
+            compute_components_for_lt(lt, out);
+            compute_components_for_ty(tcx, ty, out, visited);
+        }
+
+        ty::Dynamic(preds, lt, _) => {
+            compute_components_for_lt(lt, out);
+            for pred in preds.iter() {
+                match pred.skip_binder() {
+                    ty::ExistentialPredicate::Trait(tr) => {
+                        for arg in tr.args.iter() {
+                            compute_components_for_arg(tcx, arg, out, visited);
+                        }
+                    }
+                    ty::ExistentialPredicate::Projection(proj) => {
+                        for arg in proj.args.iter() {
+                            compute_components_for_arg(tcx, arg, out, visited);
+                        }
+                        match proj.term.kind() {
+                            ty::TermKind::Ty(ty) => {
+                                compute_components_for_ty(tcx, ty, out, visited)
+                            }
+                            ty::TermKind::Const(ct) => {
+                                compute_components_for_const(tcx, ct, out, visited)
+                            }
+                        }
+                    }
+                    ty::ExistentialPredicate::AutoTrait(..) => {}
+                }
+            }
+        }
+
+        ty::FnPtr(sig) => {
+            for ty in sig.skip_binder().inputs_and_output.iter() {
+                compute_components_for_ty(tcx, ty, out, visited);
+            }
+        }
+    }
+}
+
+/// Collect [Component]s for *all* the args of `parent`.
+///
+/// This should not be used to get the components of `parent` itself.
+/// Use [push_outlives_components] instead.
+pub fn compute_alias_components_recursive<I: Interner>(
+    tcx: I,
+    alias_ty: I::Ty,
+    out: &mut SmallVec<[Component<I>; 4]>,
+    visited: &mut SsoHashSet<I::GenericArg>,
+) {
+    let ty::Alias(kind, alias_ty) = alias_ty.kind() else {
+        unreachable!("can only call `compute_alias_components_recursive` on an alias type")
+    };
+
+    let opt_variances =
+        if kind == ty::Opaque { Some(tcx.variances_of(alias_ty.def_id)) } else { None };
+
+    for (index, child) in alias_ty.args.iter().enumerate() {
+        if opt_variances.and_then(|variances| variances.get(index)) == Some(ty::Bivariant) {
+            continue;
+        }
+        compute_components_for_arg(tcx, child, out, visited);
+    }
+}
+
+fn compute_components_for_lt<I: Interner>(lt: I::Region, out: &mut SmallVec<[Component<I>; 4]>) {
+    if !lt.is_bound() {
+        out.push(Component::Region(lt));
+    }
+}
+
+fn compute_components_for_const<I: Interner>(
+    tcx: I,
+    ct: I::Const,
+    out: &mut SmallVec<[Component<I>; 4]>,
+    visited: &mut SsoHashSet<I::GenericArg>,
+) {
+    if !visited.insert(ct.into()) {
+        return;
+    }
+    match ct.kind() {
+        ty::ConstKind::Param(_)
+        | ty::ConstKind::Bound(_, _)
+        | ty::ConstKind::Infer(_)
+        | ty::ConstKind::Placeholder(_)
+        | ty::ConstKind::Error(_) => {
+            // Trivial
+        }
+        ty::ConstKind::Expr(e) => {
+            for arg in e.args().iter() {
+                compute_components_for_arg(tcx, arg, out, visited);
+            }
+        }
+        ty::ConstKind::Value(ty, _) => {
+            compute_components_for_ty(tcx, ty, out, visited);
+        }
+        ty::ConstKind::Unevaluated(uv) => {
+            for arg in uv.args.iter() {
+                compute_components_for_arg(tcx, arg, out, visited);
+            }
+        }
+    }
+}
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 01510a61405..077483a174b 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -1495,6 +1495,14 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {
     pub fn back(&self) -> Option<&'a T> {
         self.list.back()
     }
+
+    /// Provides a reference to the cursor's parent list.
+    #[must_use]
+    #[inline(always)]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn as_list(&self) -> &'a LinkedList<T, A> {
+        self.list
+    }
 }
 
 impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
@@ -1605,6 +1613,18 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
     pub fn as_cursor(&self) -> Cursor<'_, T, A> {
         Cursor { list: self.list, current: self.current, index: self.index }
     }
+
+    /// Provides a read-only reference to the cursor's parent list.
+    ///
+    /// The lifetime of the returned reference is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the reference.
+    #[must_use]
+    #[inline(always)]
+    #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    pub fn as_list(&self) -> &LinkedList<T, A> {
+        self.list
+    }
 }
 
 // Now the list editing operations
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 61d05afccfd..a07f250d7d8 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -164,6 +164,20 @@ impl<T, A: Allocator> VecDeque<T, A> {
         self.buf.ptr()
     }
 
+    /// Appends an element to the buffer.
+    ///
+    /// # Safety
+    ///
+    /// May only be called if `deque.len() < deque.capacity()`
+    #[inline]
+    unsafe fn push_unchecked(&mut self, element: T) {
+        // SAFETY: Because of the precondition, it's guaranteed that there is space
+        // in the logical array after the last element.
+        unsafe { self.buffer_write(self.to_physical_idx(self.len), element) };
+        // This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`.
+        self.len += 1;
+    }
+
     /// Moves an element out of the buffer
     #[inline]
     unsafe fn buffer_read(&mut self, off: usize) -> T {
@@ -2911,6 +2925,14 @@ impl<T, A: Allocator> Extend<T> for VecDeque<T, A> {
     fn extend_reserve(&mut self, additional: usize) {
         self.reserve(additional);
     }
+
+    #[inline]
+    unsafe fn extend_one_unchecked(&mut self, item: T) {
+        // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly.
+        unsafe {
+            self.push_unchecked(item);
+        }
+    }
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
@@ -2928,6 +2950,14 @@ impl<'a, T: 'a + Copy, A: Allocator> Extend<&'a T> for VecDeque<T, A> {
     fn extend_reserve(&mut self, additional: usize) {
         self.reserve(additional);
     }
+
+    #[inline]
+    unsafe fn extend_one_unchecked(&mut self, &item: &'a T) {
+        // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly.
+        unsafe {
+            self.push_unchecked(item);
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs
index dccf40ccb38..6a89abc3ef9 100644
--- a/library/alloc/src/collections/vec_deque/spec_extend.rs
+++ b/library/alloc/src/collections/vec_deque/spec_extend.rs
@@ -21,21 +21,12 @@ where
         //     self.push_back(item);
         // }
 
-        // May only be called if `deque.len() < deque.capacity()`
-        unsafe fn push_unchecked<T, A: Allocator>(deque: &mut VecDeque<T, A>, element: T) {
-            // SAFETY: Because of the precondition, it's guaranteed that there is space
-            // in the logical array after the last element.
-            unsafe { deque.buffer_write(deque.to_physical_idx(deque.len), element) };
-            // This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`.
-            deque.len += 1;
-        }
-
         while let Some(element) = iter.next() {
             let (lower, _) = iter.size_hint();
             self.reserve(lower.saturating_add(1));
 
             // SAFETY: We just reserved space for at least one element.
-            unsafe { push_unchecked(self, element) };
+            unsafe { self.push_unchecked(element) };
 
             // Inner loop to avoid repeatedly calling `reserve`.
             while self.len < self.capacity() {
@@ -43,7 +34,7 @@ where
                     return;
                 };
                 // SAFETY: The loop condition guarantees that `self.len() < self.capacity()`.
-                unsafe { push_unchecked(self, element) };
+                unsafe { self.push_unchecked(element) };
             }
         }
     }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 703538d0f35..3237d8654c2 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -124,6 +124,7 @@
 #![feature(error_generic_member_access)]
 #![feature(exact_size_is_empty)]
 #![feature(extend_one)]
+#![feature(extend_one_unchecked)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(hasher_prefixfree_extras)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 90672164cb9..1983ea8281a 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -197,11 +197,7 @@ macro_rules! acquire {
 ///
 /// Sharing some immutable data between threads:
 ///
-// Note that we **do not** run these tests here. The windows builders get super
-// unhappy if a thread outlives the main thread and then exits at the same time
-// (something deadlocks) so we just avoid this entirely by not running these
-// tests.
-/// ```no_run
+/// ```
 /// use std::sync::Arc;
 /// use std::thread;
 ///
@@ -220,7 +216,7 @@ macro_rules! acquire {
 ///
 /// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize"
 ///
-/// ```no_run
+/// ```
 /// use std::sync::Arc;
 /// use std::sync::atomic::{AtomicUsize, Ordering};
 /// use std::thread;
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index f1706e31bb8..6e9b017ad75 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -3048,6 +3048,16 @@ impl<T, A: Allocator> Extend<T> for Vec<T, A> {
     fn extend_reserve(&mut self, additional: usize) {
         self.reserve(additional);
     }
+
+    #[inline]
+    unsafe fn extend_one_unchecked(&mut self, item: T) {
+        // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly.
+        unsafe {
+            let len = self.len();
+            ptr::write(self.as_mut_ptr().add(len), item);
+            self.set_len(len + 1);
+        }
+    }
 }
 
 impl<T, A: Allocator> Vec<T, A> {
@@ -3244,6 +3254,16 @@ impl<'a, T: Copy + 'a, A: Allocator> Extend<&'a T> for Vec<T, A> {
     fn extend_reserve(&mut self, additional: usize) {
         self.reserve(additional);
     }
+
+    #[inline]
+    unsafe fn extend_one_unchecked(&mut self, &item: &'a T) {
+        // SAFETY: Our preconditions ensure the space has been reserved, and `extend_reserve` is implemented correctly.
+        unsafe {
+            let len = self.len();
+            ptr::write(self.as_mut_ptr().add(len), item);
+            self.set_len(len + 1);
+        }
+    }
 }
 
 /// Implements comparison of vectors, [lexicographically](Ord#lexicographical-comparison).
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index eab11ae288a..59f3b6841d5 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -673,7 +673,7 @@ impl hash::Hash for TypeId {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for TypeId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
-        f.debug_tuple("TypeId").field(&self.as_u128()).finish()
+        write!(f, "TypeId({:#034x})", self.as_u128())
     }
 }
 
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 6d1f10f5211..88adc378477 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -10,8 +10,6 @@
 #![allow(non_camel_case_types)]
 
 use crate::fmt;
-use crate::marker::PhantomData;
-use crate::ops::{Deref, DerefMut};
 
 #[doc(no_inline)]
 #[stable(feature = "core_c_str", since = "1.64.0")]
@@ -28,6 +26,20 @@ pub use self::c_str::CStr;
 #[unstable(feature = "c_str_module", issue = "112134")]
 pub mod c_str;
 
+#[unstable(
+    feature = "c_variadic",
+    issue = "44930",
+    reason = "the `c_variadic` feature has not been properly tested on all supported platforms"
+)]
+pub use self::va_list::{VaList, VaListImpl};
+
+#[unstable(
+    feature = "c_variadic",
+    issue = "44930",
+    reason = "the `c_variadic` feature has not been properly tested on all supported platforms"
+)]
+pub mod va_list;
+
 macro_rules! type_alias {
     {
       $Docfile:tt, $Alias:ident = $Real:ty;
@@ -205,404 +217,6 @@ impl fmt::Debug for c_void {
     }
 }
 
-/// Basic implementation of a `va_list`.
-// The name is WIP, using `VaListImpl` for now.
-#[cfg(any(
-    all(
-        not(target_arch = "aarch64"),
-        not(target_arch = "powerpc"),
-        not(target_arch = "s390x"),
-        not(target_arch = "x86_64")
-    ),
-    all(target_arch = "aarch64", target_vendor = "apple"),
-    target_family = "wasm",
-    target_os = "uefi",
-    windows,
-))]
-#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-#[lang = "va_list"]
-pub struct VaListImpl<'f> {
-    ptr: *mut c_void,
-
-    // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
-    // the region of the function it's defined in
-    _marker: PhantomData<&'f mut &'f c_void>,
-}
-
-#[cfg(any(
-    all(
-        not(target_arch = "aarch64"),
-        not(target_arch = "powerpc"),
-        not(target_arch = "s390x"),
-        not(target_arch = "x86_64")
-    ),
-    all(target_arch = "aarch64", target_vendor = "apple"),
-    target_family = "wasm",
-    target_os = "uefi",
-    windows,
-))]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> fmt::Debug for VaListImpl<'f> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "va_list* {:p}", self.ptr)
-    }
-}
-
-/// AArch64 ABI implementation of a `va_list`. See the
-/// [AArch64 Procedure Call Standard] for more details.
-///
-/// [AArch64 Procedure Call Standard]:
-/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
-#[cfg(all(
-    target_arch = "aarch64",
-    not(target_vendor = "apple"),
-    not(target_os = "uefi"),
-    not(windows),
-))]
-#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
-#[derive(Debug)]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-#[lang = "va_list"]
-pub struct VaListImpl<'f> {
-    stack: *mut c_void,
-    gr_top: *mut c_void,
-    vr_top: *mut c_void,
-    gr_offs: i32,
-    vr_offs: i32,
-    _marker: PhantomData<&'f mut &'f c_void>,
-}
-
-/// PowerPC ABI implementation of a `va_list`.
-#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
-#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
-#[derive(Debug)]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-#[lang = "va_list"]
-pub struct VaListImpl<'f> {
-    gpr: u8,
-    fpr: u8,
-    reserved: u16,
-    overflow_arg_area: *mut c_void,
-    reg_save_area: *mut c_void,
-    _marker: PhantomData<&'f mut &'f c_void>,
-}
-
-/// s390x ABI implementation of a `va_list`.
-#[cfg(target_arch = "s390x")]
-#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
-#[derive(Debug)]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-#[lang = "va_list"]
-pub struct VaListImpl<'f> {
-    gpr: i64,
-    fpr: i64,
-    overflow_arg_area: *mut c_void,
-    reg_save_area: *mut c_void,
-    _marker: PhantomData<&'f mut &'f c_void>,
-}
-
-/// x86_64 ABI implementation of a `va_list`.
-#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
-#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
-#[derive(Debug)]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-#[lang = "va_list"]
-pub struct VaListImpl<'f> {
-    gp_offset: i32,
-    fp_offset: i32,
-    overflow_arg_area: *mut c_void,
-    reg_save_area: *mut c_void,
-    _marker: PhantomData<&'f mut &'f c_void>,
-}
-
-/// A wrapper for a `va_list`
-#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
-#[derive(Debug)]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-pub struct VaList<'a, 'f: 'a> {
-    #[cfg(any(
-        all(
-            not(target_arch = "aarch64"),
-            not(target_arch = "powerpc"),
-            not(target_arch = "s390x"),
-            not(target_arch = "x86_64")
-        ),
-        all(target_arch = "aarch64", target_vendor = "apple"),
-        target_family = "wasm",
-        target_os = "uefi",
-        windows,
-    ))]
-    inner: VaListImpl<'f>,
-
-    #[cfg(all(
-        any(
-            target_arch = "aarch64",
-            target_arch = "powerpc",
-            target_arch = "s390x",
-            target_arch = "x86_64"
-        ),
-        any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
-        not(target_family = "wasm"),
-        not(target_os = "uefi"),
-        not(windows),
-    ))]
-    inner: &'a mut VaListImpl<'f>,
-
-    _marker: PhantomData<&'a mut VaListImpl<'f>>,
-}
-
-#[cfg(any(
-    all(
-        not(target_arch = "aarch64"),
-        not(target_arch = "powerpc"),
-        not(target_arch = "s390x"),
-        not(target_arch = "x86_64")
-    ),
-    all(target_arch = "aarch64", target_vendor = "apple"),
-    target_family = "wasm",
-    target_os = "uefi",
-    windows,
-))]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> VaListImpl<'f> {
-    /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
-    #[inline]
-    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
-        VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
-    }
-}
-
-#[cfg(all(
-    any(
-        target_arch = "aarch64",
-        target_arch = "powerpc",
-        target_arch = "s390x",
-        target_arch = "x86_64"
-    ),
-    any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
-    not(target_family = "wasm"),
-    not(target_os = "uefi"),
-    not(windows),
-))]
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> VaListImpl<'f> {
-    /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
-    #[inline]
-    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
-        VaList { inner: self, _marker: PhantomData }
-    }
-}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
-    type Target = VaListImpl<'f>;
-
-    #[inline]
-    fn deref(&self) -> &VaListImpl<'f> {
-        &self.inner
-    }
-}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
-        &mut self.inner
-    }
-}
-
-// The VaArgSafe trait needs to be used in public interfaces, however, the trait
-// itself must not be allowed to be used outside this module. Allowing users to
-// implement the trait for a new type (thereby allowing the va_arg intrinsic to
-// be used on a new type) is likely to cause undefined behavior.
-//
-// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
-// but also ensure it cannot be used elsewhere, the trait needs to be public
-// within a private module. Once RFC 2145 has been implemented look into
-// improving this.
-mod sealed_trait {
-    /// Trait which permits the allowed types to be used with [super::VaListImpl::arg].
-    #[unstable(
-        feature = "c_variadic",
-        reason = "the `c_variadic` feature has not been properly tested on \
-                  all supported platforms",
-        issue = "44930"
-    )]
-    pub unsafe trait VaArgSafe {}
-}
-
-macro_rules! impl_va_arg_safe {
-    ($($t:ty),+) => {
-        $(
-            #[unstable(feature = "c_variadic",
-                       reason = "the `c_variadic` feature has not been properly tested on \
-                                 all supported platforms",
-                       issue = "44930")]
-            unsafe impl sealed_trait::VaArgSafe for $t {}
-        )+
-    }
-}
-
-impl_va_arg_safe! {i8, i16, i32, i64, usize}
-impl_va_arg_safe! {u8, u16, u32, u64, isize}
-impl_va_arg_safe! {f64}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-unsafe impl<T> sealed_trait::VaArgSafe for *mut T {}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-unsafe impl<T> sealed_trait::VaArgSafe for *const T {}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> VaListImpl<'f> {
-    /// Advance to the next arg.
-    #[inline]
-    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
-        // SAFETY: the caller must uphold the safety contract for `va_arg`.
-        unsafe { va_arg(self) }
-    }
-
-    /// Copies the `va_list` at the current location.
-    pub unsafe fn with_copy<F, R>(&self, f: F) -> R
-    where
-        F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
-    {
-        let mut ap = self.clone();
-        let ret = f(ap.as_va_list());
-        // SAFETY: the caller must uphold the safety contract for `va_end`.
-        unsafe {
-            va_end(&mut ap);
-        }
-        ret
-    }
-}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> Clone for VaListImpl<'f> {
-    #[inline]
-    fn clone(&self) -> Self {
-        let mut dest = crate::mem::MaybeUninit::uninit();
-        // SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal
-        unsafe {
-            va_copy(dest.as_mut_ptr(), self);
-            dest.assume_init()
-        }
-    }
-}
-
-#[unstable(
-    feature = "c_variadic",
-    reason = "the `c_variadic` feature has not been properly tested on \
-              all supported platforms",
-    issue = "44930"
-)]
-impl<'f> Drop for VaListImpl<'f> {
-    fn drop(&mut self) {
-        // FIXME: this should call `va_end`, but there's no clean way to
-        // guarantee that `drop` always gets inlined into its caller,
-        // so the `va_end` would get directly called from the same function as
-        // the corresponding `va_copy`. `man va_end` states that C requires this,
-        // and LLVM basically follows the C semantics, so we need to make sure
-        // that `va_end` is always called from the same function as `va_copy`.
-        // For more details, see https://github.com/rust-lang/rust/pull/59625
-        // and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic.
-        //
-        // This works for now, since `va_end` is a no-op on all current LLVM targets.
-    }
-}
-
-extern "rust-intrinsic" {
-    /// Destroy the arglist `ap` after initialization with `va_start` or
-    /// `va_copy`.
-    #[rustc_nounwind]
-    fn va_end(ap: &mut VaListImpl<'_>);
-
-    /// Copies the current location of arglist `src` to the arglist `dst`.
-    #[rustc_nounwind]
-    fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
-
-    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
-    /// argument `ap` points to.
-    #[rustc_nounwind]
-    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
-}
-
 // Link the MSVC default lib
 #[cfg(all(windows, target_env = "msvc"))]
 #[link(
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
new file mode 100644
index 00000000000..6a2e8b67d0c
--- /dev/null
+++ b/library/core/src/ffi/va_list.rs
@@ -0,0 +1,301 @@
+//! C's "variable arguments"
+//!
+//! Better known as "varargs".
+
+use crate::ffi::c_void;
+
+#[allow(unused_imports)]
+use crate::fmt;
+use crate::marker::PhantomData;
+use crate::ops::{Deref, DerefMut};
+
+/// Basic implementation of a `va_list`.
+// The name is WIP, using `VaListImpl` for now.
+#[cfg(any(
+    all(
+        not(target_arch = "aarch64"),
+        not(target_arch = "powerpc"),
+        not(target_arch = "s390x"),
+        not(target_arch = "x86_64")
+    ),
+    all(target_arch = "aarch64", target_vendor = "apple"),
+    target_family = "wasm",
+    target_os = "uefi",
+    windows,
+))]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
+#[lang = "va_list"]
+pub struct VaListImpl<'f> {
+    ptr: *mut c_void,
+
+    // Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
+    // the region of the function it's defined in
+    _marker: PhantomData<&'f mut &'f c_void>,
+}
+
+#[cfg(any(
+    all(
+        not(target_arch = "aarch64"),
+        not(target_arch = "powerpc"),
+        not(target_arch = "s390x"),
+        not(target_arch = "x86_64")
+    ),
+    all(target_arch = "aarch64", target_vendor = "apple"),
+    target_family = "wasm",
+    target_os = "uefi",
+    windows,
+))]
+impl<'f> fmt::Debug for VaListImpl<'f> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "va_list* {:p}", self.ptr)
+    }
+}
+
+/// AArch64 ABI implementation of a `va_list`. See the
+/// [AArch64 Procedure Call Standard] for more details.
+///
+/// [AArch64 Procedure Call Standard]:
+/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
+#[cfg(all(
+    target_arch = "aarch64",
+    not(target_vendor = "apple"),
+    not(target_os = "uefi"),
+    not(windows),
+))]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
+#[derive(Debug)]
+#[lang = "va_list"]
+pub struct VaListImpl<'f> {
+    stack: *mut c_void,
+    gr_top: *mut c_void,
+    vr_top: *mut c_void,
+    gr_offs: i32,
+    vr_offs: i32,
+    _marker: PhantomData<&'f mut &'f c_void>,
+}
+
+/// PowerPC ABI implementation of a `va_list`.
+#[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
+#[derive(Debug)]
+#[lang = "va_list"]
+pub struct VaListImpl<'f> {
+    gpr: u8,
+    fpr: u8,
+    reserved: u16,
+    overflow_arg_area: *mut c_void,
+    reg_save_area: *mut c_void,
+    _marker: PhantomData<&'f mut &'f c_void>,
+}
+
+/// s390x ABI implementation of a `va_list`.
+#[cfg(target_arch = "s390x")]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
+#[derive(Debug)]
+#[lang = "va_list"]
+pub struct VaListImpl<'f> {
+    gpr: i64,
+    fpr: i64,
+    overflow_arg_area: *mut c_void,
+    reg_save_area: *mut c_void,
+    _marker: PhantomData<&'f mut &'f c_void>,
+}
+
+/// x86_64 ABI implementation of a `va_list`.
+#[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
+#[derive(Debug)]
+#[lang = "va_list"]
+pub struct VaListImpl<'f> {
+    gp_offset: i32,
+    fp_offset: i32,
+    overflow_arg_area: *mut c_void,
+    reg_save_area: *mut c_void,
+    _marker: PhantomData<&'f mut &'f c_void>,
+}
+
+/// A wrapper for a `va_list`
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
+#[derive(Debug)]
+pub struct VaList<'a, 'f: 'a> {
+    #[cfg(any(
+        all(
+            not(target_arch = "aarch64"),
+            not(target_arch = "powerpc"),
+            not(target_arch = "s390x"),
+            not(target_arch = "x86_64")
+        ),
+        all(target_arch = "aarch64", target_vendor = "apple"),
+        target_family = "wasm",
+        target_os = "uefi",
+        windows,
+    ))]
+    inner: VaListImpl<'f>,
+
+    #[cfg(all(
+        any(
+            target_arch = "aarch64",
+            target_arch = "powerpc",
+            target_arch = "s390x",
+            target_arch = "x86_64"
+        ),
+        any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
+        not(target_family = "wasm"),
+        not(target_os = "uefi"),
+        not(windows),
+    ))]
+    inner: &'a mut VaListImpl<'f>,
+
+    _marker: PhantomData<&'a mut VaListImpl<'f>>,
+}
+
+#[cfg(any(
+    all(
+        not(target_arch = "aarch64"),
+        not(target_arch = "powerpc"),
+        not(target_arch = "s390x"),
+        not(target_arch = "x86_64")
+    ),
+    all(target_arch = "aarch64", target_vendor = "apple"),
+    target_family = "wasm",
+    target_os = "uefi",
+    windows,
+))]
+impl<'f> VaListImpl<'f> {
+    /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
+    #[inline]
+    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
+        VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
+    }
+}
+
+#[cfg(all(
+    any(
+        target_arch = "aarch64",
+        target_arch = "powerpc",
+        target_arch = "s390x",
+        target_arch = "x86_64"
+    ),
+    any(not(target_arch = "aarch64"), not(target_vendor = "apple")),
+    not(target_family = "wasm"),
+    not(target_os = "uefi"),
+    not(windows),
+))]
+impl<'f> VaListImpl<'f> {
+    /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
+    #[inline]
+    pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
+        VaList { inner: self, _marker: PhantomData }
+    }
+}
+
+impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
+    type Target = VaListImpl<'f>;
+
+    #[inline]
+    fn deref(&self) -> &VaListImpl<'f> {
+        &self.inner
+    }
+}
+
+impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
+    #[inline]
+    fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
+        &mut self.inner
+    }
+}
+
+// The VaArgSafe trait needs to be used in public interfaces, however, the trait
+// itself must not be allowed to be used outside this module. Allowing users to
+// implement the trait for a new type (thereby allowing the va_arg intrinsic to
+// be used on a new type) is likely to cause undefined behavior.
+//
+// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
+// but also ensure it cannot be used elsewhere, the trait needs to be public
+// within a private module. Once RFC 2145 has been implemented look into
+// improving this.
+mod sealed_trait {
+    /// Trait which permits the allowed types to be used with [super::VaListImpl::arg].
+    pub unsafe trait VaArgSafe {}
+}
+
+macro_rules! impl_va_arg_safe {
+    ($($t:ty),+) => {
+        $(
+            unsafe impl sealed_trait::VaArgSafe for $t {}
+        )+
+    }
+}
+
+impl_va_arg_safe! {i8, i16, i32, i64, usize}
+impl_va_arg_safe! {u8, u16, u32, u64, isize}
+impl_va_arg_safe! {f64}
+
+unsafe impl<T> sealed_trait::VaArgSafe for *mut T {}
+unsafe impl<T> sealed_trait::VaArgSafe for *const T {}
+
+impl<'f> VaListImpl<'f> {
+    /// Advance to the next arg.
+    #[inline]
+    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
+        // SAFETY: the caller must uphold the safety contract for `va_arg`.
+        unsafe { va_arg(self) }
+    }
+
+    /// Copies the `va_list` at the current location.
+    pub unsafe fn with_copy<F, R>(&self, f: F) -> R
+    where
+        F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
+    {
+        let mut ap = self.clone();
+        let ret = f(ap.as_va_list());
+        // SAFETY: the caller must uphold the safety contract for `va_end`.
+        unsafe {
+            va_end(&mut ap);
+        }
+        ret
+    }
+}
+
+impl<'f> Clone for VaListImpl<'f> {
+    #[inline]
+    fn clone(&self) -> Self {
+        let mut dest = crate::mem::MaybeUninit::uninit();
+        // SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal
+        unsafe {
+            va_copy(dest.as_mut_ptr(), self);
+            dest.assume_init()
+        }
+    }
+}
+
+impl<'f> Drop for VaListImpl<'f> {
+    fn drop(&mut self) {
+        // FIXME: this should call `va_end`, but there's no clean way to
+        // guarantee that `drop` always gets inlined into its caller,
+        // so the `va_end` would get directly called from the same function as
+        // the corresponding `va_copy`. `man va_end` states that C requires this,
+        // and LLVM basically follows the C semantics, so we need to make sure
+        // that `va_end` is always called from the same function as `va_copy`.
+        // For more details, see https://github.com/rust-lang/rust/pull/59625
+        // and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic.
+        //
+        // This works for now, since `va_end` is a no-op on all current LLVM targets.
+    }
+}
+
+extern "rust-intrinsic" {
+    /// Destroy the arglist `ap` after initialization with `va_start` or
+    /// `va_copy`.
+    #[rustc_nounwind]
+    fn va_end(ap: &mut VaListImpl<'_>);
+
+    /// Copies the current location of arglist `src` to the arglist `dst`.
+    #[rustc_nounwind]
+    fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
+
+    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
+    /// argument `ap` points to.
+    #[rustc_nounwind]
+    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
+}
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 61a45789013..86660f2e375 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -1,3 +1,5 @@
+use super::TrustedLen;
+
 /// Conversion from an [`Iterator`].
 ///
 /// By implementing `FromIterator` for a type, you define how it will be
@@ -460,6 +462,27 @@ pub trait Extend<A> {
     fn extend_reserve(&mut self, additional: usize) {
         let _ = additional;
     }
+
+    /// Extends a collection with one element, without checking there is enough capacity for it.
+    ///
+    /// # Safety
+    ///
+    /// **For callers:** This must only be called when we know the collection has enough capacity
+    /// to contain the new item, for example because we previously called `extend_reserve`.
+    ///
+    /// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is,
+    /// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words,
+    /// callers may assume that if they `extend_reserve`ed enough space they can call this method.
+
+    // This method is for internal usage only. It is only on the trait because of specialization's limitations.
+    #[unstable(feature = "extend_one_unchecked", issue = "none")]
+    #[doc(hidden)]
+    unsafe fn extend_one_unchecked(&mut self, item: A)
+    where
+        Self: Sized,
+    {
+        self.extend_one(item);
+    }
 }
 
 #[stable(feature = "extend_for_unit", since = "1.28.0")]
@@ -499,33 +522,102 @@ where
     fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
         let (a, b) = self;
         let iter = into_iter.into_iter();
+        SpecTupleExtend::extend(iter, a, b);
+    }
+
+    fn extend_one(&mut self, item: (A, B)) {
+        self.0.extend_one(item.0);
+        self.1.extend_one(item.1);
+    }
+
+    fn extend_reserve(&mut self, additional: usize) {
+        self.0.extend_reserve(additional);
+        self.1.extend_reserve(additional);
+    }
+
+    unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {
+        // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
+        unsafe {
+            self.0.extend_one_unchecked(item.0);
+            self.1.extend_one_unchecked(item.1);
+        }
+    }
+}
+
+fn default_extend_tuple<A, B, ExtendA, ExtendB>(
+    iter: impl Iterator<Item = (A, B)>,
+    a: &mut ExtendA,
+    b: &mut ExtendB,
+) where
+    ExtendA: Extend<A>,
+    ExtendB: Extend<B>,
+{
+    fn extend<'a, A, B>(
+        a: &'a mut impl Extend<A>,
+        b: &'a mut impl Extend<B>,
+    ) -> impl FnMut((), (A, B)) + 'a {
+        move |(), (t, u)| {
+            a.extend_one(t);
+            b.extend_one(u);
+        }
+    }
+
+    let (lower_bound, _) = iter.size_hint();
+    if lower_bound > 0 {
+        a.extend_reserve(lower_bound);
+        b.extend_reserve(lower_bound);
+    }
+
+    iter.fold((), extend(a, b));
+}
+
+trait SpecTupleExtend<A, B> {
+    fn extend(self, a: &mut A, b: &mut B);
+}
 
+impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
+where
+    ExtendA: Extend<A>,
+    ExtendB: Extend<B>,
+    Iter: Iterator<Item = (A, B)>,
+{
+    default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
+        default_extend_tuple(self, a, b);
+    }
+}
+
+impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
+where
+    ExtendA: Extend<A>,
+    ExtendB: Extend<B>,
+    Iter: TrustedLen<Item = (A, B)>,
+{
+    fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
         fn extend<'a, A, B>(
             a: &'a mut impl Extend<A>,
             b: &'a mut impl Extend<B>,
         ) -> impl FnMut((), (A, B)) + 'a {
-            move |(), (t, u)| {
-                a.extend_one(t);
-                b.extend_one(u);
+            // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
+            // so its `size_hint` is exact.
+            move |(), (t, u)| unsafe {
+                a.extend_one_unchecked(t);
+                b.extend_one_unchecked(u);
             }
         }
 
-        let (lower_bound, _) = iter.size_hint();
+        let (lower_bound, upper_bound) = self.size_hint();
+
+        if upper_bound.is_none() {
+            // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
+            default_extend_tuple(self, a, b);
+            return;
+        }
+
         if lower_bound > 0 {
             a.extend_reserve(lower_bound);
             b.extend_reserve(lower_bound);
         }
 
-        iter.fold((), extend(a, b));
-    }
-
-    fn extend_one(&mut self, item: (A, B)) {
-        self.0.extend_one(item.0);
-        self.1.extend_one(item.1);
-    }
-
-    fn extend_reserve(&mut self, additional: usize) {
-        self.0.extend_reserve(additional);
-        self.1.extend_reserve(additional);
+        self.fold((), extend(a, b));
     }
 }
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 9054ade2d79..dd4b6e82343 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1266,6 +1266,20 @@ impl<T> SizedTypeProperties for T {}
 /// // ^^^ error[E0616]: field `private` of struct `Struct` is private
 /// ```
 ///
+/// Only [`Sized`] fields are supported, but the container may be unsized:
+/// ```
+/// # use core::mem;
+/// #[repr(C)]
+/// pub struct Struct {
+///     a: u8,
+///     b: [u8],
+/// }
+///
+/// assert_eq!(mem::offset_of!(Struct, a), 0); // OK
+/// // assert_eq!(mem::offset_of!(Struct, b), 1);
+/// // ^^^ error[E0277]: doesn't have a size known at compile-time
+/// ```
+///
 /// Note that type layout is, in general, [subject to change and
 /// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If
 /// layout stability is required, consider using an [explicit `repr` attribute].
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 5537d26669a..68cf8203433 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -390,37 +390,26 @@ impl<T: ?Sized> *const T {
         if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
     }
 
-    /// Calculates the offset from a pointer.
+    /// Adds an offset to a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_offset`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
@@ -611,8 +600,7 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
     /// * `self` and `origin` must either
     ///
@@ -623,26 +611,10 @@ impl<T: ?Sized> *const T {
     /// * The distance between the pointers, in bytes, must be an exact multiple
     ///   of the size of `T`.
     ///
-    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
-    ///
-    /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the
-    /// address space, so two pointers within some value of any Rust type `T` will always satisfy
-    /// the last two conditions. The standard library also generally ensures that allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they
-    /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())`
-    /// always satisfies the last two conditions.
-    ///
-    /// Most platforms fundamentally can't even construct such a large allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
-    /// such large allocations either.)
+    /// As a consequence, the absolute distance between the pointers, in bytes, computed on
+    /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
+    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// than `isize::MAX` bytes.
     ///
     /// The requirement for pointers to be derived from the same allocated object is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
@@ -879,37 +851,26 @@ impl<T: ?Sized> *const T {
         }
     }
 
-    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a `usize`.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_add`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
@@ -963,7 +924,7 @@ impl<T: ?Sized> *const T {
         unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
     }
 
-    /// Calculates the offset from a pointer (convenience for
+    /// Subtracts an offset from a pointer (convenience for
     /// `.offset((count as isize).wrapping_neg())`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -971,30 +932,19 @@ impl<T: ?Sized> *const T {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
-    ///
-    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a usize.
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_sub`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 30d5b2cfc5a..0dc910db5b9 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -404,37 +404,26 @@ impl<T: ?Sized> *mut T {
         if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
     }
 
-    /// Calculates the offset from a pointer.
+    /// Adds an offset to a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_offset`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
@@ -836,8 +825,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
     /// * `self` and `origin` must either
     ///
@@ -848,26 +836,10 @@ impl<T: ?Sized> *mut T {
     /// * The distance between the pointers, in bytes, must be an exact multiple
     ///   of the size of `T`.
     ///
-    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
-    ///
-    /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the
-    /// address space, so two pointers within some value of any Rust type `T` will always satisfy
-    /// the last two conditions. The standard library also generally ensures that allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they
-    /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())`
-    /// always satisfies the last two conditions.
-    ///
-    /// Most platforms fundamentally can't even construct such a large allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
-    /// such large allocations either.)
+    /// As a consequence, the absolute distance between the pointers, in bytes, computed on
+    /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
+    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// than `isize::MAX` bytes.
     ///
     /// The requirement for pointers to be derived from the same allocated object is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
@@ -1020,37 +992,26 @@ impl<T: ?Sized> *mut T {
         unsafe { (self as *const T).sub_ptr(origin) }
     }
 
-    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a `usize`.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_add`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
@@ -1104,7 +1065,7 @@ impl<T: ?Sized> *mut T {
         unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
     }
 
-    /// Calculates the offset from a pointer (convenience for
+    /// Subtracts an offset from a pointer (convenience for
     /// `.offset((count as isize).wrapping_neg())`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -1112,30 +1073,19 @@ impl<T: ?Sized> *mut T {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * If the computed offset, **in bytes**, is non-zero, then both the starting and resulting
-    ///   pointer must be either in bounds or at the end of the same [allocated object].
-    ///   (If it is zero, then the function is always well-defined.)
-    ///
-    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a usize.
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// Consider using [`wrapping_sub`] instead if these constraints are
     /// difficult to satisfy. The only advantage of this method is that it
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 0504a0fc32f..75a99e14fda 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -476,36 +476,26 @@ impl<T: ?Sized> NonNull<T> {
         unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
     }
 
-    /// Calculates the offset from a pointer.
+    /// Adds an offset to a pointer.
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same [allocated object].
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
-    ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// [allocated object]: crate::ptr#allocated-object
     ///
@@ -562,36 +552,26 @@ impl<T: ?Sized> NonNull<T> {
         unsafe { NonNull { pointer: self.pointer.byte_offset(count) } }
     }
 
-    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    /// Adds an offset to a pointer (convenience for `.offset(count as isize)`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same [allocated object].
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * The computed offset, **in bytes**, cannot overflow an `isize`.
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a `usize`.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len())` is always safe.
-    ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// [allocated object]: crate::ptr#allocated-object
     ///
@@ -649,7 +629,7 @@ impl<T: ?Sized> NonNull<T> {
         unsafe { NonNull { pointer: self.pointer.byte_add(count) } }
     }
 
-    /// Calculates the offset from a pointer (convenience for
+    /// Subtracts an offset from a pointer (convenience for
     /// `.offset((count as isize).wrapping_neg())`).
     ///
     /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
@@ -657,29 +637,19 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
-    ///
-    /// * Both the starting and resulting pointer must be either in bounds or one
-    ///   byte past the end of the same [allocated object].
-    ///
-    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * The offset being in bounds cannot rely on "wrapping around" the address
-    ///   space. That is, the infinite-precision sum must fit in a usize.
+    /// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`.
     ///
-    /// The compiler and standard library generally tries to ensure allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec`
-    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
-    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
+    ///   [allocated object], and the entire memory range between `self` and the result must be in
+    ///   bounds of that allocated object. In particular, this range must not "wrap around" the edge
+    ///   of the address space.
     ///
-    /// Most platforms fundamentally can't even construct such an allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
+    /// Allocated objects can never be larger than `isize::MAX` bytes, so if the computed offset
+    /// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.
+    /// This implies, for instance, that `vec.as_ptr().add(vec.len())` (for `vec: Vec<T>`) is always
+    /// safe.
     ///
     /// [allocated object]: crate::ptr#allocated-object
     ///
@@ -761,38 +731,21 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// # Safety
     ///
-    /// If any of the following conditions are violated, the result is Undefined
-    /// Behavior:
+    /// If any of the following conditions are violated, the result is Undefined Behavior:
     ///
-    /// * Both `self` and `origin` must be either in bounds or one
-    ///   byte past the end of the same [allocated object].
+    /// * `self` and `origin` must either
     ///
-    /// * Both pointers must be *derived from* a pointer to the same object.
-    ///   (See below for an example.)
+    ///   * both be *derived from* a pointer to the same [allocated object], and the memory range between
+    ///     the two pointers must be either empty or in bounds of that object. (See below for an example.)
+    ///   * or both be derived from an integer literal/constant, and point to the same address.
     ///
     /// * The distance between the pointers, in bytes, must be an exact multiple
     ///   of the size of `T`.
     ///
-    /// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
-    ///
-    /// * The distance being in bounds cannot rely on "wrapping around" the address space.
-    ///
-    /// Rust types are never larger than `isize::MAX` and Rust allocations never wrap around the
-    /// address space, so two pointers within some value of any Rust type `T` will always satisfy
-    /// the last two conditions. The standard library also generally ensures that allocations
-    /// never reach a size where an offset is a concern. For instance, `Vec` and `Box` ensure they
-    /// never allocate more than `isize::MAX` bytes, so `ptr_into_vec.offset_from(vec.as_ptr())`
-    /// always satisfies the last two conditions.
-    ///
-    /// Most platforms fundamentally can't even construct such a large allocation.
-    /// For instance, no known 64-bit platform can ever serve a request
-    /// for 2<sup>63</sup> bytes due to page-table limitations or splitting the address space.
-    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
-    /// more than `isize::MAX` bytes with things like Physical Address
-    /// Extension. As such, memory acquired directly from allocators or memory
-    /// mapped files *may* be too large to handle with this function.
-    /// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
-    /// such large allocations either.)
+    /// As a consequence, the absolute distance between the pointers, in bytes, computed on
+    /// mathematical integers (without "wrapping around"), cannot overflow an `isize`. This is
+    /// implied by the in-bounds requirement, and the fact that no allocated object can be larger
+    /// than `isize::MAX` bytes.
     ///
     /// The requirement for pointers to be derived from the same allocated object is primarily
     /// needed for `const`-compatibility: the distance between pointers into *different* allocated
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 8d565e26a16..d5121a554bf 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3192,15 +3192,19 @@ impl Hash for Path {
         let bytes = &bytes[prefix_len..];
 
         let mut component_start = 0;
-        let mut bytes_hashed = 0;
+        // track some extra state to avoid prefix collisions.
+        // ["foo", "bar"] and ["foobar"], will have the same payload bytes
+        // but result in different chunk_bits
+        let mut chunk_bits: usize = 0;
 
         for i in 0..bytes.len() {
             let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) };
             if is_sep {
                 if i > component_start {
                     let to_hash = &bytes[component_start..i];
+                    chunk_bits = chunk_bits.wrapping_add(to_hash.len());
+                    chunk_bits = chunk_bits.rotate_right(2);
                     h.write(to_hash);
-                    bytes_hashed += to_hash.len();
                 }
 
                 // skip over separator and optionally a following CurDir item
@@ -3221,11 +3225,12 @@ impl Hash for Path {
 
         if component_start < bytes.len() {
             let to_hash = &bytes[component_start..];
+            chunk_bits = chunk_bits.wrapping_add(to_hash.len());
+            chunk_bits = chunk_bits.rotate_right(2);
             h.write(to_hash);
-            bytes_hashed += to_hash.len();
         }
 
-        h.write_usize(bytes_hashed);
+        h.write_usize(chunk_bits);
     }
 }
 
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index bb6126e4941..3ade4fb892f 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1619,6 +1619,20 @@ pub fn test_compare() {
     relative_from: Some("")
     );
 
+    tc!("foo//", "foo",
+    eq: true,
+    starts_with: true,
+    ends_with: true,
+    relative_from: Some("")
+    );
+
+    tc!("foo///", "foo",
+    eq: true,
+    starts_with: true,
+    ends_with: true,
+    relative_from: Some("")
+    );
+
     tc!("foo/.", "foo",
     eq: true,
     starts_with: true,
@@ -1633,6 +1647,20 @@ pub fn test_compare() {
     relative_from: Some("")
     );
 
+    tc!("foo/.//bar", "foo/bar",
+    eq: true,
+    starts_with: true,
+    ends_with: true,
+    relative_from: Some("")
+    );
+
+    tc!("foo//./bar", "foo/bar",
+    eq: true,
+    starts_with: true,
+    ends_with: true,
+    relative_from: Some("")
+    );
+
     tc!("foo/bar", "foo",
     eq: false,
     starts_with: true,
@@ -1640,6 +1668,13 @@ pub fn test_compare() {
     relative_from: Some("bar")
     );
 
+    tc!("foo/bar", "foobar",
+    eq: false,
+    starts_with: false,
+    ends_with: false,
+    relative_from: None
+    );
+
     tc!("foo/bar/baz", "foo/bar",
     eq: false,
     starts_with: true,
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index f52b9e52c54..fe243550606 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -80,14 +80,21 @@ use crate::sync::Once;
 /// static LIST: OnceList<u32> = OnceList::new();
 /// static COUNTER: AtomicU32 = AtomicU32::new(0);
 ///
-/// let vec = (0..thread::available_parallelism().unwrap().get()).map(|_| thread::spawn(|| {
-///     while let i @ 0..=1000 = COUNTER.fetch_add(1, Ordering::Relaxed) {
-///         LIST.push(i);
+/// # const LEN: u32 = if cfg!(miri) { 50 } else { 1000 };
+/// # /*
+/// const LEN: u32 = 1000;
+/// # */
+/// thread::scope(|s| {
+///     for _ in 0..thread::available_parallelism().unwrap().get() {
+///         s.spawn(|| {
+///             while let i @ 0..LEN = COUNTER.fetch_add(1, Ordering::Relaxed) {
+///                 LIST.push(i);
+///             }
+///         });
 ///     }
-/// })).collect::<Vec<thread::JoinHandle<_>>>();
-/// vec.into_iter().for_each(|handle| handle.join().unwrap());
+/// });
 ///
-/// for i in 0..=1000 {
+/// for i in 0..LEN {
 ///     assert!(LIST.contains(&i));
 /// }
 ///
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index 479af4af666..a4be6bc56c5 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -85,7 +85,7 @@ macro_rules! clean_crate_tree {
 
                 // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file,
                 // and doesn't use `stream_cargo` to avoid passing `--message-format` which `clean` doesn't accept.
-                builder.run(cargo);
+                cargo.run(builder);
             }
         }
     )+ }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 01b25224de4..11a7a404535 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -27,7 +27,7 @@ use crate::core::builder::crate_description;
 use crate::core::builder::Cargo;
 use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
 use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::utils::helpers::{
     exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
 };
@@ -773,20 +773,19 @@ impl Step for StartupObjects {
             let src_file = &src_dir.join(file.to_string() + ".rs");
             let dst_file = &dst_dir.join(file.to_string() + ".o");
             if !up_to_date(src_file, dst_file) {
-                let mut cmd = BootstrapCommand::new(&builder.initial_rustc);
+                let mut cmd = command(&builder.initial_rustc);
                 cmd.env("RUSTC_BOOTSTRAP", "1");
                 if !builder.local_rebuild {
                     // a local_rebuild compiler already has stage1 features
                     cmd.arg("--cfg").arg("bootstrap");
                 }
-                builder.run(
-                    cmd.arg("--target")
-                        .arg(target.rustc_target_arg())
-                        .arg("--emit=obj")
-                        .arg("-o")
-                        .arg(dst_file)
-                        .arg(src_file),
-                );
+                cmd.arg("--target")
+                    .arg(target.rustc_target_arg())
+                    .arg("--emit=obj")
+                    .arg("-o")
+                    .arg(dst_file)
+                    .arg(src_file)
+                    .run(builder);
             }
 
             let target = sysroot_dir.join((*file).to_string() + ".o");
@@ -1488,10 +1487,10 @@ pub fn compiler_file(
     if builder.config.dry_run() {
         return PathBuf::new();
     }
-    let mut cmd = BootstrapCommand::new(compiler);
+    let mut cmd = command(compiler);
     cmd.args(builder.cflags(target, GitRepo::Rustc, c));
     cmd.arg(format!("-print-file-name={file}"));
-    let out = builder.run(cmd.capture_stdout()).stdout();
+    let out = cmd.capture_stdout().run(builder).stdout();
     PathBuf::from(out.trim())
 }
 
@@ -1836,9 +1835,8 @@ impl Step for Assemble {
             let llvm::LlvmResult { llvm_config, .. } =
                 builder.ensure(llvm::Llvm { target: target_compiler.host });
             if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
-                let llvm_bin_dir = builder
-                    .run(BootstrapCommand::new(llvm_config).capture_stdout().arg("--bindir"))
-                    .stdout();
+                let llvm_bin_dir =
+                    command(llvm_config).capture_stdout().arg("--bindir").run(builder).stdout();
                 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
 
                 // Since we've already built the LLVM tools, install them to the sysroot.
@@ -2163,7 +2161,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path)
     }
 
     let previous_mtime = FileTime::from_last_modification_time(&path.metadata().unwrap());
-    builder.run(BootstrapCommand::new("strip").capture().arg("--strip-debug").arg(path));
+    command("strip").capture().arg("--strip-debug").arg(path).run(builder);
 
     // After running `strip`, we have to set the file modification time to what it was before,
     // otherwise we risk Cargo invalidating its fingerprint and rebuilding the world next time
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 3dc871b1ca9..7bc5405e92f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -25,7 +25,7 @@ use crate::core::build_steps::tool::{self, Tool};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::utils::channel::{self, Info};
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 use crate::utils::helpers::{
     exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
 };
@@ -180,9 +180,9 @@ fn make_win_dist(
     }
 
     //Ask gcc where it keeps its stuff
-    let mut cmd = BootstrapCommand::new(builder.cc(target));
+    let mut cmd = command(builder.cc(target));
     cmd.arg("-print-search-dirs");
-    let gcc_out = builder.run(cmd.capture_stdout()).stdout();
+    let gcc_out = cmd.capture_stdout().run(builder).stdout();
 
     let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
     let mut lib_path = Vec::new();
@@ -1023,7 +1023,7 @@ impl Step for PlainSourceTarball {
             }
 
             // Vendor all Cargo dependencies
-            let mut cmd = BootstrapCommand::new(&builder.initial_cargo);
+            let mut cmd = command(&builder.initial_cargo);
             cmd.arg("vendor")
                 .arg("--versioned-dirs")
                 .arg("--sync")
@@ -1061,7 +1061,7 @@ impl Step for PlainSourceTarball {
             }
 
             let config = if !builder.config.dry_run() {
-                builder.run(cmd.capture()).stdout()
+                cmd.capture().run(builder).stdout()
             } else {
                 String::new()
             };
@@ -1599,14 +1599,14 @@ impl Step for Extended {
             let _ = fs::remove_dir_all(&pkg);
 
             let pkgbuild = |component: &str| {
-                let mut cmd = BootstrapCommand::new("pkgbuild");
+                let mut cmd = command("pkgbuild");
                 cmd.arg("--identifier")
                     .arg(format!("org.rust-lang.{}", component))
                     .arg("--scripts")
                     .arg(pkg.join(component))
                     .arg("--nopayload")
                     .arg(pkg.join(component).with_extension("pkg"));
-                builder.run(cmd);
+                cmd.run(builder);
             };
 
             let prepare = |name: &str| {
@@ -1636,7 +1636,7 @@ impl Step for Extended {
             builder.create_dir(&pkg.join("res"));
             builder.create(&pkg.join("res/LICENSE.txt"), &license);
             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
-            let mut cmd = BootstrapCommand::new("productbuild");
+            let mut cmd = command("productbuild");
             cmd.arg("--distribution")
                 .arg(xform(&etc.join("pkg/Distribution.xml")))
                 .arg("--resources")
@@ -1649,7 +1649,7 @@ impl Step for Extended {
                 .arg("--package-path")
                 .arg(&pkg);
             let _time = timeit(builder);
-            builder.run(cmd);
+            cmd.run(builder);
         }
 
         if target.is_windows() {
@@ -1703,168 +1703,159 @@ impl Step for Extended {
             let light = wix.join("bin/light.exe");
 
             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
-            builder.run(
-                BootstrapCommand::new(&heat)
+            command(&heat)
+                .current_dir(&exe)
+                .arg("dir")
+                .arg("rustc")
+                .args(heat_flags)
+                .arg("-cg")
+                .arg("RustcGroup")
+                .arg("-dr")
+                .arg("Rustc")
+                .arg("-var")
+                .arg("var.RustcDir")
+                .arg("-out")
+                .arg(exe.join("RustcGroup.wxs"))
+                .run(builder);
+            if built_tools.contains("rust-docs") {
+                command(&heat)
                     .current_dir(&exe)
                     .arg("dir")
-                    .arg("rustc")
+                    .arg("rust-docs")
                     .args(heat_flags)
                     .arg("-cg")
-                    .arg("RustcGroup")
+                    .arg("DocsGroup")
                     .arg("-dr")
-                    .arg("Rustc")
+                    .arg("Docs")
                     .arg("-var")
-                    .arg("var.RustcDir")
+                    .arg("var.DocsDir")
                     .arg("-out")
-                    .arg(exe.join("RustcGroup.wxs")),
-            );
-            if built_tools.contains("rust-docs") {
-                builder.run(
-                    BootstrapCommand::new(&heat)
-                        .current_dir(&exe)
-                        .arg("dir")
-                        .arg("rust-docs")
-                        .args(heat_flags)
-                        .arg("-cg")
-                        .arg("DocsGroup")
-                        .arg("-dr")
-                        .arg("Docs")
-                        .arg("-var")
-                        .arg("var.DocsDir")
-                        .arg("-out")
-                        .arg(exe.join("DocsGroup.wxs"))
-                        .arg("-t")
-                        .arg(etc.join("msi/squash-components.xsl")),
-                );
+                    .arg(exe.join("DocsGroup.wxs"))
+                    .arg("-t")
+                    .arg(etc.join("msi/squash-components.xsl"))
+                    .run(builder);
             }
-            builder.run(
-                BootstrapCommand::new(&heat)
+            command(&heat)
+                .current_dir(&exe)
+                .arg("dir")
+                .arg("cargo")
+                .args(heat_flags)
+                .arg("-cg")
+                .arg("CargoGroup")
+                .arg("-dr")
+                .arg("Cargo")
+                .arg("-var")
+                .arg("var.CargoDir")
+                .arg("-out")
+                .arg(exe.join("CargoGroup.wxs"))
+                .arg("-t")
+                .arg(etc.join("msi/remove-duplicates.xsl"))
+                .run(builder);
+            command(&heat)
+                .current_dir(&exe)
+                .arg("dir")
+                .arg("rust-std")
+                .args(heat_flags)
+                .arg("-cg")
+                .arg("StdGroup")
+                .arg("-dr")
+                .arg("Std")
+                .arg("-var")
+                .arg("var.StdDir")
+                .arg("-out")
+                .arg(exe.join("StdGroup.wxs"))
+                .run(builder);
+            if built_tools.contains("rust-analyzer") {
+                command(&heat)
                     .current_dir(&exe)
                     .arg("dir")
-                    .arg("cargo")
+                    .arg("rust-analyzer")
                     .args(heat_flags)
                     .arg("-cg")
-                    .arg("CargoGroup")
+                    .arg("RustAnalyzerGroup")
                     .arg("-dr")
-                    .arg("Cargo")
+                    .arg("RustAnalyzer")
                     .arg("-var")
-                    .arg("var.CargoDir")
+                    .arg("var.RustAnalyzerDir")
                     .arg("-out")
-                    .arg(exe.join("CargoGroup.wxs"))
+                    .arg(exe.join("RustAnalyzerGroup.wxs"))
                     .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
-            builder.run(
-                BootstrapCommand::new(&heat)
+                    .arg(etc.join("msi/remove-duplicates.xsl"))
+                    .run(builder);
+            }
+            if built_tools.contains("clippy") {
+                command(&heat)
                     .current_dir(&exe)
                     .arg("dir")
-                    .arg("rust-std")
+                    .arg("clippy")
                     .args(heat_flags)
                     .arg("-cg")
-                    .arg("StdGroup")
+                    .arg("ClippyGroup")
                     .arg("-dr")
-                    .arg("Std")
+                    .arg("Clippy")
                     .arg("-var")
-                    .arg("var.StdDir")
+                    .arg("var.ClippyDir")
                     .arg("-out")
-                    .arg(exe.join("StdGroup.wxs")),
-            );
-            if built_tools.contains("rust-analyzer") {
-                builder.run(
-                    BootstrapCommand::new(&heat)
-                        .current_dir(&exe)
-                        .arg("dir")
-                        .arg("rust-analyzer")
-                        .args(heat_flags)
-                        .arg("-cg")
-                        .arg("RustAnalyzerGroup")
-                        .arg("-dr")
-                        .arg("RustAnalyzer")
-                        .arg("-var")
-                        .arg("var.RustAnalyzerDir")
-                        .arg("-out")
-                        .arg(exe.join("RustAnalyzerGroup.wxs"))
-                        .arg("-t")
-                        .arg(etc.join("msi/remove-duplicates.xsl")),
-                );
-            }
-            if built_tools.contains("clippy") {
-                builder.run(
-                    BootstrapCommand::new(&heat)
-                        .current_dir(&exe)
-                        .arg("dir")
-                        .arg("clippy")
-                        .args(heat_flags)
-                        .arg("-cg")
-                        .arg("ClippyGroup")
-                        .arg("-dr")
-                        .arg("Clippy")
-                        .arg("-var")
-                        .arg("var.ClippyDir")
-                        .arg("-out")
-                        .arg(exe.join("ClippyGroup.wxs"))
-                        .arg("-t")
-                        .arg(etc.join("msi/remove-duplicates.xsl")),
-                );
+                    .arg(exe.join("ClippyGroup.wxs"))
+                    .arg("-t")
+                    .arg(etc.join("msi/remove-duplicates.xsl"))
+                    .run(builder);
             }
             if built_tools.contains("miri") {
-                builder.run(
-                    BootstrapCommand::new(&heat)
-                        .current_dir(&exe)
-                        .arg("dir")
-                        .arg("miri")
-                        .args(heat_flags)
-                        .arg("-cg")
-                        .arg("MiriGroup")
-                        .arg("-dr")
-                        .arg("Miri")
-                        .arg("-var")
-                        .arg("var.MiriDir")
-                        .arg("-out")
-                        .arg(exe.join("MiriGroup.wxs"))
-                        .arg("-t")
-                        .arg(etc.join("msi/remove-duplicates.xsl")),
-                );
-            }
-            builder.run(
-                BootstrapCommand::new(&heat)
+                command(&heat)
                     .current_dir(&exe)
                     .arg("dir")
-                    .arg("rust-analysis")
+                    .arg("miri")
                     .args(heat_flags)
                     .arg("-cg")
-                    .arg("AnalysisGroup")
+                    .arg("MiriGroup")
                     .arg("-dr")
-                    .arg("Analysis")
+                    .arg("Miri")
                     .arg("-var")
-                    .arg("var.AnalysisDir")
+                    .arg("var.MiriDir")
                     .arg("-out")
-                    .arg(exe.join("AnalysisGroup.wxs"))
+                    .arg(exe.join("MiriGroup.wxs"))
                     .arg("-t")
-                    .arg(etc.join("msi/remove-duplicates.xsl")),
-            );
+                    .arg(etc.join("msi/remove-duplicates.xsl"))
+                    .run(builder);
+            }
+            command(&heat)
+                .current_dir(&exe)
+                .arg("dir")
+                .arg("rust-analysis")
+                .args(heat_flags)
+                .arg("-cg")
+                .arg("AnalysisGroup")
+                .arg("-dr")
+                .arg("Analysis")
+                .arg("-var")
+                .arg("var.AnalysisDir")
+                .arg("-out")
+                .arg(exe.join("AnalysisGroup.wxs"))
+                .arg("-t")
+                .arg(etc.join("msi/remove-duplicates.xsl"))
+                .run(builder);
             if target.ends_with("windows-gnu") {
-                builder.run(
-                    BootstrapCommand::new(&heat)
-                        .current_dir(&exe)
-                        .arg("dir")
-                        .arg("rust-mingw")
-                        .args(heat_flags)
-                        .arg("-cg")
-                        .arg("GccGroup")
-                        .arg("-dr")
-                        .arg("Gcc")
-                        .arg("-var")
-                        .arg("var.GccDir")
-                        .arg("-out")
-                        .arg(exe.join("GccGroup.wxs")),
-                );
+                command(&heat)
+                    .current_dir(&exe)
+                    .arg("dir")
+                    .arg("rust-mingw")
+                    .args(heat_flags)
+                    .arg("-cg")
+                    .arg("GccGroup")
+                    .arg("-dr")
+                    .arg("Gcc")
+                    .arg("-var")
+                    .arg("var.GccDir")
+                    .arg("-out")
+                    .arg(exe.join("GccGroup.wxs"))
+                    .run(builder);
             }
 
             let candle = |input: &Path| {
                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
-                let mut cmd = BootstrapCommand::new(&candle);
+                let mut cmd = command(&candle);
                 cmd.current_dir(&exe)
                     .arg("-nologo")
                     .arg("-dRustcDir=rustc")
@@ -1893,7 +1884,7 @@ impl Step for Extended {
                 if target.ends_with("windows-gnu") {
                     cmd.arg("-dGccDir=rust-mingw");
                 }
-                builder.run(cmd);
+                cmd.run(builder);
             };
             candle(&xform(&etc.join("msi/rust.wxs")));
             candle(&etc.join("msi/ui.wxs"));
@@ -1925,7 +1916,7 @@ impl Step for Extended {
 
             builder.info(&format!("building `msi` installer with {light:?}"));
             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
-            let mut cmd = BootstrapCommand::new(&light);
+            let mut cmd = command(&light);
             cmd.arg("-nologo")
                 .arg("-ext")
                 .arg("WixUIExtension")
@@ -1962,7 +1953,7 @@ impl Step for Extended {
             cmd.arg("-sice:ICE57");
 
             let _time = timeit(builder);
-            builder.run(cmd);
+            cmd.run(builder);
 
             if !builder.config.dry_run() {
                 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
@@ -2078,13 +2069,13 @@ fn maybe_install_llvm(
     } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
         llvm::prebuilt_llvm_config(builder, target)
     {
-        let mut cmd = BootstrapCommand::new(llvm_config);
+        let mut cmd = command(llvm_config);
         cmd.arg("--libfiles");
         builder.verbose(|| println!("running {cmd:?}"));
         let files = if builder.config.dry_run() {
             "".into()
         } else {
-            builder.run(cmd.capture_stdout()).stdout()
+            cmd.capture_stdout().run(builder).stdout()
         };
         let build_llvm_out = &builder.llvm_out(builder.config.build);
         let target_llvm_out = &builder.llvm_out(target);
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 823e842693e..4b35d6c5d4c 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -154,7 +154,7 @@ impl<P: Step> Step for RustbookSrc<P> {
             builder.info(&format!("Rustbook ({target}) - {name}"));
             let _ = fs::remove_dir_all(&out);
 
-            builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out));
+            rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder);
 
             for lang in &self.languages {
                 let out = out.join(lang);
@@ -162,10 +162,15 @@ impl<P: Step> Step for RustbookSrc<P> {
                 builder.info(&format!("Rustbook ({target}) - {name} - {lang}"));
                 let _ = fs::remove_dir_all(&out);
 
-                let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
-                builder.run(
-                    rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).arg("-l").arg(lang),
-                );
+                builder
+                    .tool_cmd(Tool::Rustbook)
+                    .arg("build")
+                    .arg(&src)
+                    .arg("-d")
+                    .arg(&out)
+                    .arg("-l")
+                    .arg(lang)
+                    .run(builder);
             }
         }
 
@@ -301,7 +306,7 @@ fn invoke_rustdoc(
         cmd.arg("-Z").arg("unstable-options").arg("--disable-minification");
     }
 
-    builder.run(cmd);
+    cmd.run(builder);
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -395,7 +400,7 @@ impl Step for Standalone {
             } else {
                 cmd.arg("--markdown-css").arg("rust.css");
             }
-            builder.run(cmd);
+            cmd.run(builder);
         }
 
         // We open doc/index.html as the default if invoked as `x.py doc --open`
@@ -494,7 +499,7 @@ impl Step for Releases {
                 cmd.arg("--disable-minification");
             }
 
-            builder.run(cmd);
+            cmd.run(builder);
         }
 
         // We open doc/RELEASES.html as the default if invoked as `x.py doc --open RELEASES.md`
@@ -738,7 +743,7 @@ fn doc_std(
         format!("library{} in {} format", crate_description(requested_crates), format.as_str());
     let _guard = builder.msg_doc(compiler, description, target);
 
-    builder.run(cargo.into_cmd());
+    cargo.into_cmd().run(builder);
     builder.cp_link_r(&out_dir, out);
 }
 
@@ -863,7 +868,7 @@ impl Step for Rustc {
         let proc_macro_out_dir = builder.stage_out(compiler, Mode::Rustc).join("doc");
         symlink_dir_force(&builder.config, &out, &proc_macro_out_dir);
 
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
 
         if !builder.config.dry_run() {
             // Sanity check on linked compiler crates
@@ -996,7 +1001,7 @@ macro_rules! tool_doc {
                 symlink_dir_force(&builder.config, &out, &proc_macro_out_dir);
 
                 let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target);
-                builder.run(cargo.into_cmd());
+                cargo.into_cmd().run(builder);
 
                 if !builder.config.dry_run() {
                     // Sanity check on linked doc directories
@@ -1075,12 +1080,7 @@ impl Step for ErrorIndex {
         builder.info(&format!("Documenting error index ({})", self.target));
         let out = builder.doc_out(self.target);
         t!(fs::create_dir_all(&out));
-        let mut index = tool::ErrorIndex::command(builder);
-        index.arg("html");
-        index.arg(out);
-        index.arg(&builder.version);
-
-        builder.run(index);
+        tool::ErrorIndex::command(builder).arg("html").arg(out).arg(&builder.version).run(builder);
     }
 }
 
@@ -1116,7 +1116,7 @@ impl Step for UnstableBookGen {
         cmd.arg(builder.src.join("src"));
         cmd.arg(out);
 
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
 
@@ -1211,7 +1211,7 @@ impl Step for RustcBook {
             self.compiler.host,
             self.target,
         );
-        builder.run(cmd);
+        cmd.run(builder);
         drop(doc_generator_guard);
 
         // Run rustbook/mdbook to generate the HTML pages.
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index 66286a52813..d3ac2bae1e8 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -1,7 +1,7 @@
 //! Runs rustfmt on the repository.
 
 use crate::core::builder::Builder;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::utils::helpers::{self, program_out_of_date, t};
 use build_helper::ci::CiEnv;
 use build_helper::git::get_git_modified_files;
@@ -54,13 +54,13 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F
 fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> {
     let stamp_file = build.out.join("rustfmt.stamp");
 
-    let mut cmd = BootstrapCommand::new(match build.initial_rustfmt() {
+    let mut cmd = command(match build.initial_rustfmt() {
         Some(p) => p,
         None => return None,
     });
     cmd.arg("--version");
 
-    let output = build.run(cmd.capture().allow_failure());
+    let output = cmd.capture().allow_failure().run(build);
     if output.is_failure() {
         return None;
     }
@@ -160,29 +160,25 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
         }
     }
     let git_available =
-        build.run(helpers::git(None).capture().allow_failure().arg("--version")).is_success();
+        helpers::git(None).capture().allow_failure().arg("--version").run(build).is_success();
 
     let mut adjective = None;
     if git_available {
-        let in_working_tree = build
-            .run(
-                helpers::git(Some(&build.src))
-                    .capture()
-                    .allow_failure()
-                    .arg("rev-parse")
-                    .arg("--is-inside-work-tree"),
-            )
+        let in_working_tree = helpers::git(Some(&build.src))
+            .capture()
+            .allow_failure()
+            .arg("rev-parse")
+            .arg("--is-inside-work-tree")
+            .run(build)
             .is_success();
         if in_working_tree {
-            let untracked_paths_output = build
-                .run(
-                    helpers::git(Some(&build.src))
-                        .capture_stdout()
-                        .arg("status")
-                        .arg("--porcelain")
-                        .arg("-z")
-                        .arg("--untracked-files=normal"),
-                )
+            let untracked_paths_output = helpers::git(Some(&build.src))
+                .capture_stdout()
+                .arg("status")
+                .arg("--porcelain")
+                .arg("-z")
+                .arg("--untracked-files=normal")
+                .run(build)
                 .stdout();
             let untracked_paths: Vec<_> = untracked_paths_output
                 .split_terminator('\0')
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 7ee1aca2abc..d3e9d6d7875 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -10,7 +10,7 @@ use std::path::{Component, Path, PathBuf};
 use crate::core::build_steps::dist;
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::core::config::{Config, TargetSelection};
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::utils::helpers::t;
 use crate::utils::tarball::GeneratedTarball;
 use crate::{Compiler, Kind};
@@ -102,7 +102,7 @@ fn install_sh(
     let empty_dir = builder.out.join("tmp/empty_dir");
     t!(fs::create_dir_all(&empty_dir));
 
-    let mut cmd = BootstrapCommand::new(SHELL);
+    let mut cmd = command(SHELL);
     cmd.current_dir(&empty_dir)
         .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
         .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
@@ -113,7 +113,7 @@ fn install_sh(
         .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
         .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
         .arg("--disable-ldconfig");
-    builder.run(cmd);
+    cmd.run(builder);
     t!(fs::remove_dir_all(&empty_dir));
 }
 
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 4f1c1f87d1c..bff731e13b0 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -24,7 +24,7 @@ use crate::utils::helpers::{
 };
 use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind};
 
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use build_helper::ci::CiEnv;
 use build_helper::git::get_git_merge_base;
 
@@ -478,9 +478,8 @@ impl Step for Llvm {
             let LlvmResult { llvm_config, .. } =
                 builder.ensure(Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
-                let llvm_bindir = builder
-                    .run(BootstrapCommand::new(&llvm_config).capture_stdout().arg("--bindir"))
-                    .stdout();
+                let llvm_bindir =
+                    command(&llvm_config).capture_stdout().arg("--bindir").run(builder).stdout();
                 let host_bin = Path::new(llvm_bindir.trim());
                 cfg.define(
                     "LLVM_TABLEGEN",
@@ -530,8 +529,8 @@ impl Step for Llvm {
 
         // Helper to find the name of LLVM's shared library on darwin and linux.
         let find_llvm_lib_name = |extension| {
-            let cmd = BootstrapCommand::new(&res.llvm_config);
-            let version = builder.run(cmd.capture_stdout().arg("--version")).stdout();
+            let version =
+                command(&res.llvm_config).capture_stdout().arg("--version").run(builder).stdout();
             let major = version.split('.').next().unwrap();
 
             match &llvm_version_suffix {
@@ -587,8 +586,7 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
         return;
     }
 
-    let cmd = BootstrapCommand::new(llvm_config);
-    let version = builder.run(cmd.capture_stdout().arg("--version")).stdout();
+    let version = command(llvm_config).capture_stdout().arg("--version").run(builder).stdout();
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
         if major >= 17 {
diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs
index f41b5fe10f1..5b83080a326 100644
--- a/src/bootstrap/src/core/build_steps/perf.rs
+++ b/src/bootstrap/src/core/build_steps/perf.rs
@@ -31,5 +31,5 @@ Consider setting `rust.debuginfo-level = 1` in `config.toml`."#);
         .env("PERF_COLLECTOR", collector)
         .env("PERF_RESULT_DIR", profile_results_dir)
         .args(args);
-    builder.run(&mut cmd);
+    cmd.run(builder);
 }
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 316a03a2171..3a2d3f67522 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -11,7 +11,7 @@ use crate::core::build_steps::tool::{self, SourceType, Tool};
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::core::config::flags::get_completion;
 use crate::core::config::TargetSelection;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::Mode;
 
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
@@ -40,8 +40,7 @@ impl Step for BuildManifest {
             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
         });
 
-        let today =
-            builder.run(BootstrapCommand::new("date").capture_stdout().arg("+%Y-%m-%d")).stdout();
+        let today = command("date").capture_stdout().arg("+%Y-%m-%d").run(builder).stdout();
 
         cmd.arg(sign);
         cmd.arg(distdir(builder));
@@ -50,7 +49,7 @@ impl Step for BuildManifest {
         cmd.arg(&builder.config.channel);
 
         builder.create_dir(&distdir(builder));
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
 
@@ -72,7 +71,7 @@ impl Step for BumpStage0 {
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let mut cmd = builder.tool_cmd(Tool::BumpStage0);
         cmd.args(builder.config.args());
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
 
@@ -94,7 +93,7 @@ impl Step for ReplaceVersionPlaceholder {
     fn run(self, builder: &Builder<'_>) -> Self::Output {
         let mut cmd = builder.tool_cmd(Tool::ReplaceVersionPlaceholder);
         cmd.arg(&builder.src);
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
 
@@ -158,7 +157,7 @@ impl Step for Miri {
         // after another --, so this must be at the end.
         miri.args(builder.config.args());
 
-        builder.run(miri.into_cmd());
+        miri.into_cmd().run(builder);
     }
 }
 
@@ -188,7 +187,7 @@ impl Step for CollectLicenseMetadata {
         let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
         cmd.env("REUSE_EXE", reuse);
         cmd.env("DEST", &dest);
-        builder.run(cmd);
+        cmd.run(builder);
 
         dest
     }
@@ -218,7 +217,7 @@ impl Step for GenerateCopyright {
         let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
         cmd.env("LICENSE_METADATA", &license_metadata);
         cmd.env("DEST", &dest);
-        builder.run(cmd);
+        cmd.run(builder);
 
         dest
     }
@@ -242,7 +241,7 @@ impl Step for GenerateWindowsSys {
     fn run(self, builder: &Builder<'_>) {
         let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
         cmd.arg(&builder.src);
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index 5412b3c807b..2d4409d27c6 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -13,13 +13,11 @@ use crate::core::builder::Builder;
 pub fn suggest(builder: &Builder<'_>, run: bool) {
     let git_config = builder.config.git_config();
     let suggestions = builder
-        .run(
-            builder
-                .tool_cmd(Tool::SuggestTests)
-                .capture_stdout()
-                .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository)
-                .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch),
-        )
+        .tool_cmd(Tool::SuggestTests)
+        .capture_stdout()
+        .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository)
+        .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch)
+        .run(builder)
         .stdout();
 
     let suggestions = suggestions
diff --git a/src/bootstrap/src/core/build_steps/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
index a115ba2d8b2..021680302cd 100644
--- a/src/bootstrap/src/core/build_steps/synthetic_targets.rs
+++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs
@@ -9,7 +9,7 @@
 
 use crate::core::builder::{Builder, ShouldRun, Step};
 use crate::core::config::TargetSelection;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::Compiler;
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -56,7 +56,7 @@ fn create_synthetic_target(
         return TargetSelection::create_synthetic(&name, path.to_str().unwrap());
     }
 
-    let mut cmd = BootstrapCommand::new(builder.rustc(compiler));
+    let mut cmd = command(builder.rustc(compiler));
     cmd.arg("--target").arg(base.rustc_target_arg());
     cmd.args(["-Zunstable-options", "--print", "target-spec-json"]);
 
@@ -64,7 +64,7 @@ fn create_synthetic_target(
     // we cannot use nightly features. So `RUSTC_BOOTSTRAP` is needed here.
     cmd.env("RUSTC_BOOTSTRAP", "1");
 
-    let output = builder.run(cmd.capture()).stdout();
+    let output = cmd.capture().run(builder).stdout();
     let mut spec: serde_json::Value = serde_json::from_slice(output.as_bytes()).unwrap();
     let spec_map = spec.as_object_mut().unwrap();
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index dc53bd3cfa7..7f4c4bd53df 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -26,7 +26,7 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::flags::get_completion;
 use crate::core::config::flags::Subcommand;
 use crate::core::config::TargetSelection;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 use crate::utils::helpers::{
     self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
     linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date, LldThreads,
@@ -155,7 +155,7 @@ You can skip linkcheck with --skip src/tools/linkchecker"
         let _guard =
             builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host);
         let _time = helpers::timeit(builder);
-        builder.run(linkchecker.delay_failure().arg(builder.out.join(host.triple).join("doc")));
+        linkchecker.delay_failure().arg(builder.out.join(host.triple).join("doc")).run(builder);
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -212,9 +212,11 @@ impl Step for HtmlCheck {
             builder,
         ));
 
-        builder.run(
-            builder.tool_cmd(Tool::HtmlChecker).delay_failure().arg(builder.doc_out(self.target)),
-        );
+        builder
+            .tool_cmd(Tool::HtmlChecker)
+            .delay_failure()
+            .arg(builder.doc_out(self.target))
+            .run(builder);
     }
 }
 
@@ -259,7 +261,7 @@ impl Step for Cargotest {
             .env("RUSTC", builder.rustc(compiler))
             .env("RUSTDOC", builder.rustdoc(compiler));
         add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
-        builder.run(cmd.delay_failure());
+        cmd.delay_failure().run(builder);
     }
 }
 
@@ -460,7 +462,7 @@ impl Miri {
         let mut cargo = BootstrapCommand::from(cargo);
         let _guard =
             builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target);
-        builder.run(&mut cargo);
+        cargo.run(builder);
 
         // # Determine where Miri put its sysroot.
         // To this end, we run `cargo miri setup --print-sysroot` and capture the output.
@@ -473,7 +475,7 @@ impl Miri {
             String::new()
         } else {
             builder.verbose(|| println!("running: {cargo:?}"));
-            let stdout = builder.run(cargo.capture_stdout()).stdout();
+            let stdout = cargo.capture_stdout().run(builder).stdout();
             // Output is "<sysroot>\n".
             let sysroot = stdout.trim_end();
             builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
@@ -561,7 +563,7 @@ impl Step for Miri {
         {
             let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target);
             let _time = helpers::timeit(builder);
-            builder.run(&mut cargo);
+            cargo.run(builder);
         }
 
         // Run it again for mir-opt-level 4 to catch some miscompilations.
@@ -583,7 +585,7 @@ impl Step for Miri {
                     target,
                 );
                 let _time = helpers::timeit(builder);
-                builder.run(cargo);
+                cargo.run(builder);
             }
         }
     }
@@ -648,11 +650,11 @@ impl Step for CargoMiri {
 
         // Finally, pass test-args and run everything.
         cargo.arg("--").args(builder.config.test_args());
-        let cargo = BootstrapCommand::from(cargo);
+        let mut cargo = BootstrapCommand::from(cargo);
         {
             let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target);
             let _time = helpers::timeit(builder);
-            builder.run(cargo);
+            cargo.run(builder);
         }
     }
 }
@@ -753,7 +755,7 @@ impl Step for Clippy {
         let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
 
         // Clippy reports errors if it blessed the outputs
-        if builder.run(cargo.allow_failure()).is_success() {
+        if cargo.allow_failure().run(builder).is_success() {
             // The tests succeeded; nothing to do.
             return;
         }
@@ -806,7 +808,7 @@ impl Step for RustdocTheme {
             .env("RUSTC_BOOTSTRAP", "1");
         cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
 
-        builder.run(cmd.delay_failure());
+        cmd.delay_failure().run(builder);
     }
 }
 
@@ -832,7 +834,7 @@ impl Step for RustdocJSStd {
     fn run(self, builder: &Builder<'_>) {
         let nodejs =
             builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
-        let mut command = BootstrapCommand::new(nodejs);
+        let mut command = command(nodejs);
         command
             .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
             .arg("--crate-name")
@@ -866,7 +868,7 @@ impl Step for RustdocJSStd {
             builder.config.build,
             self.target,
         );
-        builder.run(command);
+        command.run(builder);
     }
 }
 
@@ -908,12 +910,12 @@ fn get_browser_ui_test_version_inner(
     npm: &Path,
     global: bool,
 ) -> Option<String> {
-    let mut command = BootstrapCommand::new(npm).capture();
+    let mut command = command(npm).capture();
     command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
     if global {
         command.arg("--global");
     }
-    let lines = builder.run(command.allow_failure()).stdout();
+    let lines = command.allow_failure().run(builder).stdout();
     lines
         .lines()
         .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
@@ -1085,7 +1087,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
         }
 
         builder.info("tidy check");
-        builder.run(cmd.delay_failure());
+        cmd.delay_failure().run(builder);
 
         builder.info("x.py completions check");
         let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"]
@@ -1292,7 +1294,7 @@ impl Step for RunMakeSupport {
             &[],
         );
 
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
 
         let lib_name = "librun_make_support.rlib";
         let lib = builder.tools_dir(self.compiler).join(lib_name);
@@ -1804,14 +1806,20 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
-        let lldb_version = builder
-            .run(BootstrapCommand::new(&lldb_exe).capture().allow_failure().arg("--version"))
+        let lldb_version = command(&lldb_exe)
+            .capture()
+            .allow_failure()
+            .arg("--version")
+            .run(builder)
             .stdout_if_ok()
             .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
         if let Some(ref vers) = lldb_version {
             cmd.arg("--lldb-version").arg(vers);
-            let lldb_python_dir = builder
-                .run(BootstrapCommand::new(&lldb_exe).allow_failure().capture_stdout().arg("-P"))
+            let lldb_python_dir = command(&lldb_exe)
+                .allow_failure()
+                .capture_stdout()
+                .arg("-P")
+                .run(builder)
                 .stdout_if_ok()
                 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
             if let Some(ref dir) = lldb_python_dir {
@@ -1869,11 +1877,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             let llvm::LlvmResult { llvm_config, .. } =
                 builder.ensure(llvm::Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
-                let llvm_version = builder
-                    .run(BootstrapCommand::new(&llvm_config).capture_stdout().arg("--version"))
-                    .stdout();
+                let llvm_version =
+                    builder.run(command(&llvm_config).capture_stdout().arg("--version")).stdout();
                 let llvm_components = builder
-                    .run(BootstrapCommand::new(&llvm_config).capture_stdout().arg("--components"))
+                    .run(command(&llvm_config).capture_stdout().arg("--components"))
                     .stdout();
                 // Remove trailing newline from llvm-config output.
                 cmd.arg("--llvm-version")
@@ -1893,9 +1900,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             // separate compilations. We can add LLVM's library path to the
             // platform-specific environment variable as a workaround.
             if !builder.config.dry_run() && suite.ends_with("fulldeps") {
-                let llvm_libdir = builder
-                    .run(BootstrapCommand::new(&llvm_config).capture_stdout().arg("--libdir"))
-                    .stdout();
+                let llvm_libdir =
+                    builder.run(command(&llvm_config).capture_stdout().arg("--libdir")).stdout();
                 add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd);
             }
 
@@ -2169,9 +2175,11 @@ impl BookTest {
             compiler.host,
         );
         let _time = helpers::timeit(builder);
-        let cmd = rustbook_cmd.delay_failure();
-        let toolstate =
-            if builder.run(cmd).is_success() { ToolState::TestPass } else { ToolState::TestFail };
+        let toolstate = if rustbook_cmd.delay_failure().run(builder).is_success() {
+            ToolState::TestPass
+        } else {
+            ToolState::TestFail
+        };
         builder.save_toolstate(self.name, toolstate);
     }
 
@@ -2300,7 +2308,7 @@ impl Step for ErrorIndex {
         let guard =
             builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
         let _time = helpers::timeit(builder);
-        builder.run(tool.capture());
+        tool.capture().run(builder);
         drop(guard);
         // The tests themselves need to link to std, so make sure it is
         // available.
@@ -2333,7 +2341,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
     if !builder.config.verbose_tests {
         cmd = cmd.capture();
     }
-    builder.run(cmd).is_success()
+    cmd.run(builder).is_success()
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -2359,7 +2367,7 @@ impl Step for RustcGuide {
         let src = builder.src.join(relative_path);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook).delay_failure();
         rustbook_cmd.arg("linkcheck").arg(&src);
-        let toolstate = if builder.run(rustbook_cmd).is_success() {
+        let toolstate = if rustbook_cmd.run(builder).is_success() {
             ToolState::TestPass
         } else {
             ToolState::TestFail
@@ -2863,19 +2871,19 @@ impl Step for RemoteCopyLibs {
 
         // Spawn the emulator and wait for it to come online
         let tool = builder.tool_exe(Tool::RemoteTestClient);
-        let mut cmd = BootstrapCommand::new(&tool);
+        let mut cmd = command(&tool);
         cmd.arg("spawn-emulator").arg(target.triple).arg(&server).arg(builder.tempdir());
         if let Some(rootfs) = builder.qemu_rootfs(target) {
             cmd.arg(rootfs);
         }
-        builder.run(cmd);
+        cmd.run(builder);
 
         // Push all our dylibs to the emulator
         for f in t!(builder.sysroot_libdir(compiler, target).read_dir()) {
             let f = t!(f);
             let name = f.file_name().into_string().unwrap();
             if helpers::is_dylib(&name) {
-                builder.run(BootstrapCommand::new(&tool).arg("push").arg(f.path()));
+                builder.run(command(&tool).arg("push").arg(f.path()));
             }
         }
     }
@@ -2906,22 +2914,20 @@ impl Step for Distcheck {
         builder.ensure(dist::PlainSourceTarball);
         builder.ensure(dist::Src);
 
-        let mut cmd = BootstrapCommand::new("tar");
+        let mut cmd = command("tar");
         cmd.arg("-xf")
             .arg(builder.ensure(dist::PlainSourceTarball).tarball())
             .arg("--strip-components=1")
             .current_dir(&dir);
-        builder.run(cmd);
+        cmd.run(builder);
         builder.run(
-            BootstrapCommand::new("./configure")
+            command("./configure")
                 .args(&builder.config.configure_args)
                 .arg("--enable-vendor")
                 .current_dir(&dir),
         );
         builder.run(
-            BootstrapCommand::new(helpers::make(&builder.config.build.triple))
-                .arg("check")
-                .current_dir(&dir),
+            command(helpers::make(&builder.config.build.triple)).arg("check").current_dir(&dir),
         );
 
         // Now make sure that rust-src has all of libstd's dependencies
@@ -2930,16 +2936,16 @@ impl Step for Distcheck {
         let _ = fs::remove_dir_all(&dir);
         t!(fs::create_dir_all(&dir));
 
-        let mut cmd = BootstrapCommand::new("tar");
+        let mut cmd = command("tar");
         cmd.arg("-xf")
             .arg(builder.ensure(dist::Src).tarball())
             .arg("--strip-components=1")
             .current_dir(&dir);
-        builder.run(cmd);
+        cmd.run(builder);
 
         let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
         builder.run(
-            BootstrapCommand::new(&builder.initial_cargo)
+            command(&builder.initial_cargo)
                 // Will read the libstd Cargo.toml
                 // which uses the unstable `public-dependency` feature.
                 .env("RUSTC_BOOTSTRAP", "1")
@@ -2968,7 +2974,7 @@ impl Step for Bootstrap {
         // Some tests require cargo submodule to be present.
         builder.build.update_submodule(Path::new("src/tools/cargo"));
 
-        let mut check_bootstrap = BootstrapCommand::new(builder.python());
+        let mut check_bootstrap = command(builder.python());
         check_bootstrap
             .args(["-m", "unittest", "bootstrap_test.py"])
             .env("BUILD_DIR", &builder.out)
@@ -2976,9 +2982,9 @@ impl Step for Bootstrap {
             .current_dir(builder.src.join("src/bootstrap/"));
         // NOTE: we intentionally don't pass test_args here because the args for unittest and cargo test are mutually incompatible.
         // Use `python -m unittest` manually if you want to pass arguments.
-        builder.run(check_bootstrap.delay_failure());
+        check_bootstrap.delay_failure().run(builder);
 
-        let mut cmd = BootstrapCommand::new(&builder.initial_cargo);
+        let mut cmd = command(&builder.initial_cargo);
         cmd.arg("test")
             .args(["--features", "bootstrap-self-test"])
             .current_dir(builder.src.join("src/bootstrap"))
@@ -3053,7 +3059,7 @@ impl Step for TierCheck {
             self.compiler.host,
             self.compiler.host,
         );
-        builder.run(BootstrapCommand::from(cargo).delay_failure());
+        BootstrapCommand::from(cargo).delay_failure().run(builder);
     }
 }
 
@@ -3129,7 +3135,7 @@ impl Step for RustInstaller {
             return;
         }
 
-        let mut cmd = BootstrapCommand::new(builder.src.join("src/tools/rust-installer/test.sh"));
+        let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
         let tmpdir = testdir(builder, compiler.host).join("rust-installer");
         let _ = std::fs::remove_dir_all(&tmpdir);
         let _ = std::fs::create_dir_all(&tmpdir);
@@ -3138,7 +3144,7 @@ impl Step for RustInstaller {
         cmd.env("CARGO", &builder.initial_cargo);
         cmd.env("RUSTC", &builder.initial_rustc);
         cmd.env("TMP_DIR", &tmpdir);
-        builder.run(cmd.delay_failure());
+        cmd.delay_failure().run(builder);
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -3332,7 +3338,7 @@ impl Step for CodegenCranelift {
             .arg("testsuite.extended_sysroot");
         cargo.args(builder.config.test_args());
 
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
     }
 }
 
@@ -3457,6 +3463,6 @@ impl Step for CodegenGCC {
             .arg("--std-tests");
         cargo.args(builder.config.test_args());
 
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 5fb282db90a..ad92a01bce7 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -8,7 +8,7 @@ use crate::core::builder;
 use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::utils::channel::GitInfo;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 use crate::utils::helpers::{add_dylib_path, exe, t};
 use crate::Compiler;
 use crate::Mode;
@@ -438,7 +438,7 @@ impl ErrorIndex {
         // for rustc_private and libLLVM.so, and `sysroot_lib` for libstd, etc.
         let host = builder.config.build;
         let compiler = builder.compiler_for(builder.top_stage, host, host);
-        let mut cmd = BootstrapCommand::new(builder.ensure(ErrorIndex { compiler }));
+        let mut cmd = command(builder.ensure(ErrorIndex { compiler }));
         let mut dylib_paths = builder.rustc_lib_paths(compiler);
         dylib_paths.push(PathBuf::from(&builder.sysroot_libdir(compiler, compiler.host)));
         add_dylib_path(dylib_paths, &mut cmd);
@@ -602,7 +602,7 @@ impl Step for Rustdoc {
             &self.compiler.host,
             &target,
         );
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
 
         // Cargo adds a number of paths to the dylib search path on windows, which results in
         // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
@@ -857,7 +857,7 @@ impl Step for LlvmBitcodeLinker {
             &self.extra_features,
         );
 
-        builder.run(cargo.into_cmd());
+        cargo.into_cmd().run(builder);
 
         let tool_out = builder
             .cargo_out(self.compiler, Mode::ToolRustc, self.target)
@@ -912,21 +912,20 @@ impl Step for LibcxxVersionTool {
             }
 
             let compiler = builder.cxx(self.target).unwrap();
-            let mut cmd = BootstrapCommand::new(compiler);
+            let mut cmd = command(compiler);
 
             cmd.arg("-o")
                 .arg(&executable)
                 .arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
 
-            builder.run(cmd);
+            cmd.run(builder);
 
             if !executable.exists() {
                 panic!("Something went wrong. {} is not present", executable.display());
             }
         }
 
-        let version_output =
-            builder.run(BootstrapCommand::new(executable).capture_stdout()).stdout();
+        let version_output = command(executable).capture_stdout().run(builder).stdout();
 
         let version_str = version_output.split_once("version:").unwrap().1;
         let version = version_str.trim().parse::<usize>().unwrap();
@@ -1050,7 +1049,7 @@ impl<'a> Builder<'a> {
     /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for
     /// `host`.
     pub fn tool_cmd(&self, tool: Tool) -> BootstrapCommand {
-        let mut cmd = BootstrapCommand::new(self.tool_exe(tool));
+        let mut cmd = command(self.tool_exe(tool));
         let compiler = self.compiler(0, self.config.build);
         let host = &compiler.host;
         // Prepares the `cmd` provided to be able to run the `compiler` provided.
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 0b999a24a1f..62342ee4792 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -1,5 +1,5 @@
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use std::path::{Path, PathBuf};
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -27,7 +27,7 @@ impl Step for Vendor {
     }
 
     fn run(self, builder: &Builder<'_>) -> Self::Output {
-        let mut cmd = BootstrapCommand::new(&builder.initial_cargo);
+        let mut cmd = command(&builder.initial_cargo);
         cmd.arg("vendor");
 
         if self.versioned_dirs {
@@ -59,6 +59,6 @@ impl Step for Vendor {
 
         cmd.current_dir(self.root_dir);
 
-        builder.run(cmd);
+        cmd.run(builder);
     }
 }
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 4da912994c3..24bb96c6b88 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -23,7 +23,7 @@ use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, t, LldThreads};
 use crate::EXTRA_CHECK_CFGS;
 use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode};
 
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 pub use crate::Compiler;
 
 use clap::ValueEnum;
@@ -1254,7 +1254,7 @@ impl<'a> Builder<'a> {
         if run_compiler.stage == 0 {
             // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy.
             let cargo_clippy = self.build.config.download_clippy();
-            let mut cmd = BootstrapCommand::new(cargo_clippy);
+            let mut cmd = command(cargo_clippy);
             cmd.env("CARGO", &self.initial_cargo);
             return cmd;
         }
@@ -1273,7 +1273,7 @@ impl<'a> Builder<'a> {
         let mut dylib_path = helpers::dylib_path();
         dylib_path.insert(0, self.sysroot(run_compiler).join("lib"));
 
-        let mut cmd = BootstrapCommand::new(cargo_clippy);
+        let mut cmd = command(cargo_clippy);
         cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap());
         cmd.env("CARGO", &self.initial_cargo);
         cmd
@@ -1295,7 +1295,7 @@ impl<'a> Builder<'a> {
             extra_features: Vec::new(),
         });
         // Invoke cargo-miri, make sure it can find miri and cargo.
-        let mut cmd = BootstrapCommand::new(cargo_miri);
+        let mut cmd = command(cargo_miri);
         cmd.env("MIRI", &miri);
         cmd.env("CARGO", &self.initial_cargo);
         // Need to add the `run_compiler` libs. Those are the libs produces *by* `build_compiler`,
@@ -1311,7 +1311,7 @@ impl<'a> Builder<'a> {
     }
 
     pub fn rustdoc_cmd(&self, compiler: Compiler) -> BootstrapCommand {
-        let mut cmd = BootstrapCommand::new(self.bootstrap_out.join("rustdoc"));
+        let mut cmd = command(self.bootstrap_out.join("rustdoc"));
         cmd.env("RUSTC_STAGE", compiler.stage.to_string())
             .env("RUSTC_SYSROOT", self.sysroot(compiler))
             // Note that this is *not* the sysroot_libdir because rustdoc must be linked
@@ -1365,7 +1365,7 @@ impl<'a> Builder<'a> {
             cargo = self.cargo_miri_cmd(compiler);
             cargo.arg("miri").arg(subcmd);
         } else {
-            cargo = BootstrapCommand::new(&self.initial_cargo);
+            cargo = command(&self.initial_cargo);
             cargo.arg(cmd);
         }
 
@@ -1918,9 +1918,8 @@ impl<'a> Builder<'a> {
         // platform-specific environment variable as a workaround.
         if mode == Mode::ToolRustc || mode == Mode::Codegen {
             if let Some(llvm_config) = self.llvm_config(target) {
-                let llvm_libdir = self
-                    .run(BootstrapCommand::new(llvm_config).capture_stdout().arg("--libdir"))
-                    .stdout();
+                let llvm_libdir =
+                    command(llvm_config).capture_stdout().arg("--libdir").run(self).stdout();
                 add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cargo);
             }
         }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index c35398e2eb7..a7f4bb0cf14 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -11,7 +11,7 @@ use std::{
 use build_helper::ci::CiEnv;
 use xz2::bufread::XzDecoder;
 
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 use crate::utils::helpers::hex_encode;
 use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
 use crate::{t, Config};
@@ -212,7 +212,7 @@ impl Config {
     fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) {
         println!("downloading {url}");
         // Try curl. If that fails and we are on windows, fallback to PowerShell.
-        let mut curl = BootstrapCommand::new("curl");
+        let mut curl = command("curl");
         curl.args([
             "-y",
             "30",
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 49d17107125..b18da844014 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -2,7 +2,7 @@ use std::path::PathBuf;
 
 use serde_derive::Deserialize;
 
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::{t, Build, Crate};
 
 /// For more information, see the output of
@@ -70,7 +70,7 @@ pub fn build(build: &mut Build) {
 /// particular crate (e.g., `x build sysroot` to build library/sysroot).
 fn workspace_members(build: &Build) -> Vec<Package> {
     let collect_metadata = |manifest_path| {
-        let mut cargo = BootstrapCommand::new(&build.initial_cargo);
+        let mut cargo = command(&build.initial_cargo);
         cargo
             // Will read the libstd Cargo.toml
             // which uses the unstable `public-dependency` feature.
@@ -81,7 +81,7 @@ fn workspace_members(build: &Build) -> Vec<Package> {
             .arg("--no-deps")
             .arg("--manifest-path")
             .arg(build.src.join(manifest_path));
-        let metadata_output = build.run(cargo.capture_stdout().run_always()).stdout();
+        let metadata_output = cargo.capture_stdout().run_always().run(build).stdout();
         let Output { packages, .. } = t!(serde_json::from_str(&metadata_output));
         packages
     };
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 78862ccb8cd..9995da3a1e5 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -23,7 +23,7 @@ use std::collections::HashSet;
 
 use crate::builder::Kind;
 use crate::core::config::Target;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::command;
 use crate::Build;
 
 pub struct Finder {
@@ -209,9 +209,7 @@ than building it.
 
     #[cfg(not(feature = "bootstrap-self-test"))]
     let stage0_supported_target_list: HashSet<String> = crate::utils::helpers::output(
-        &mut BootstrapCommand::new(&build.config.initial_rustc)
-            .args(["--print", "target-list"])
-            .command,
+        &mut command(&build.config.initial_rustc).args(["--print", "target-list"]).command,
     )
     .lines()
     .map(|s| s.to_string())
@@ -354,8 +352,7 @@ than building it.
             // There are three builds of cmake on windows: MSVC, MinGW, and
             // Cygwin. The Cygwin build does not have generators for Visual
             // Studio, so detect that here and error.
-            let out =
-                build.run(BootstrapCommand::new("cmake").capture_stdout().arg("--help")).stdout();
+            let out = command("cmake").capture_stdout().arg("--help").run(build).stdout();
             if !out.contains("Visual Studio") {
                 panic!(
                     "
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index ffdd9bc885a..f16afb29796 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -41,7 +41,7 @@ use crate::core::builder::Kind;
 use crate::core::config::{flags, LldMode};
 use crate::core::config::{DryRun, Target};
 use crate::core::config::{LlvmLibunwind, TargetSelection};
-use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput};
+use crate::utils::exec::{command, BehaviorOnFailure, BootstrapCommand, CommandOutput};
 use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
 
 mod core;
@@ -510,9 +510,10 @@ impl Build {
         }
 
         println!("Updating submodule {}", relative_path.display());
-        self.run(
-            helpers::git(Some(&self.src)).args(["submodule", "-q", "sync"]).arg(relative_path),
-        );
+        helpers::git(Some(&self.src))
+            .args(["submodule", "-q", "sync"])
+            .arg(relative_path)
+            .run(self);
 
         // Try passing `--progress` to start, then run git again without if that fails.
         let update = |progress: bool| {
@@ -548,23 +549,25 @@ impl Build {
         };
         // NOTE: doesn't use `try_run` because this shouldn't print an error if it fails.
         if !update(true).command.status().map_or(false, |status| status.success()) {
-            self.run(update(false));
+            update(false).run(self);
         }
 
         // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error).
         // diff-index reports the modifications through the exit status
-        let has_local_modifications = self
-            .run(submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]))
+        let has_local_modifications = submodule_git()
+            .allow_failure()
+            .args(["diff-index", "--quiet", "HEAD"])
+            .run(self)
             .is_failure();
         if has_local_modifications {
-            self.run(submodule_git().args(["stash", "push"]));
+            submodule_git().args(["stash", "push"]).run(self);
         }
 
-        self.run(submodule_git().args(["reset", "-q", "--hard"]));
-        self.run(submodule_git().args(["clean", "-qdfx"]));
+        submodule_git().args(["reset", "-q", "--hard"]).run(self);
+        submodule_git().args(["clean", "-qdfx"]).run(self);
 
         if has_local_modifications {
-            self.run(submodule_git().args(["stash", "pop"]));
+            submodule_git().args(["stash", "pop"]).run(self);
         }
     }
 
@@ -575,14 +578,12 @@ impl Build {
         if !self.config.submodules(self.rust_info()) {
             return;
         }
-        let output = self
-            .run(
-                helpers::git(Some(&self.src))
-                    .capture()
-                    .args(["config", "--file"])
-                    .arg(self.config.src.join(".gitmodules"))
-                    .args(["--get-regexp", "path"]),
-            )
+        let output = helpers::git(Some(&self.src))
+            .capture()
+            .args(["config", "--file"])
+            .arg(self.config.src.join(".gitmodules"))
+            .args(["--get-regexp", "path"])
+            .run(self)
             .stdout();
         for line in output.lines() {
             // Look for `submodule.$name.path = $path`
@@ -860,16 +861,14 @@ impl Build {
         if let Some(s) = target_config.and_then(|c| c.llvm_filecheck.as_ref()) {
             s.to_path_buf()
         } else if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
-            let llvm_bindir =
-                self.run(BootstrapCommand::new(s).capture_stdout().arg("--bindir")).stdout();
+            let llvm_bindir = command(s).capture_stdout().arg("--bindir").run(self).stdout();
             let filecheck = Path::new(llvm_bindir.trim()).join(exe("FileCheck", target));
             if filecheck.exists() {
                 filecheck
             } else {
                 // On Fedora the system LLVM installs FileCheck in the
                 // llvm subdirectory of the libdir.
-                let llvm_libdir =
-                    self.run(BootstrapCommand::new(s).capture_stdout().arg("--libdir")).stdout();
+                let llvm_libdir = command(s).capture_stdout().arg("--libdir").run(self).stdout();
                 let lib_filecheck =
                     Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", target));
                 if lib_filecheck.exists() {
@@ -935,8 +934,7 @@ impl Build {
 
     /// Execute a command and return its output.
     /// This method should be used for all command executions in bootstrap.
-    fn run<C: AsMut<BootstrapCommand>>(&self, mut command: C) -> CommandOutput {
-        let command = command.as_mut();
+    fn run(&self, command: &mut BootstrapCommand) -> CommandOutput {
         if self.config.dry_run() && !command.run_always {
             return CommandOutput::default();
         }
@@ -1496,18 +1494,17 @@ impl Build {
             // Figure out how many merge commits happened since we branched off master.
             // That's our beta number!
             // (Note that we use a `..` range, not the `...` symmetric difference.)
-            self.run(
-                helpers::git(Some(&self.src))
-                    .capture()
-                    .arg("rev-list")
-                    .arg("--count")
-                    .arg("--merges")
-                    .arg(format!(
-                        "refs/remotes/origin/{}..HEAD",
-                        self.config.stage0_metadata.config.nightly_branch
-                    )),
-            )
-            .stdout()
+            helpers::git(Some(&self.src))
+                .capture()
+                .arg("rev-list")
+                .arg("--count")
+                .arg("--merges")
+                .arg(format!(
+                    "refs/remotes/origin/{}..HEAD",
+                    self.config.stage0_metadata.config.nightly_branch
+                ))
+                .run(self)
+                .stdout()
         });
         let n = count.trim().parse().unwrap();
         self.prerelease_version.set(Some(n));
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index b80df545202..d6fa7fc0bbe 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -26,7 +26,7 @@ use std::path::{Path, PathBuf};
 use std::{env, iter};
 
 use crate::core::config::TargetSelection;
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 use crate::{Build, CLang, GitRepo};
 
 // The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
@@ -183,14 +183,14 @@ fn default_compiler(
             }
 
             let cmd = BootstrapCommand::from(c.to_command());
-            let output = build.run(cmd.capture_stdout().arg("--version")).stdout();
+            let output = cmd.capture_stdout().arg("--version").run(build).stdout();
             let i = output.find(" 4.")?;
             match output[i + 3..].chars().next().unwrap() {
                 '0'..='6' => {}
                 _ => return None,
             }
             let alternative = format!("e{gnu_compiler}");
-            if build.run(BootstrapCommand::new(&alternative).capture()).is_success() {
+            if command(&alternative).capture().run(build).is_success() {
                 Some(PathBuf::from(alternative))
             } else {
                 None
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 086d10c6351..ba963f52dc2 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -1,3 +1,4 @@
+use crate::Build;
 use std::ffi::OsStr;
 use std::path::Path;
 use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output, Stdio};
@@ -108,14 +109,17 @@ impl BootstrapCommand {
         self
     }
 
+    #[must_use]
     pub fn delay_failure(self) -> Self {
         Self { failure_behavior: BehaviorOnFailure::DelayFail, ..self }
     }
 
+    #[must_use]
     pub fn fail_fast(self) -> Self {
         Self { failure_behavior: BehaviorOnFailure::Exit, ..self }
     }
 
+    #[must_use]
     pub fn allow_failure(self) -> Self {
         Self { failure_behavior: BehaviorOnFailure::Ignore, ..self }
     }
@@ -126,21 +130,20 @@ impl BootstrapCommand {
     }
 
     /// Capture all output of the command, do not print it.
+    #[must_use]
     pub fn capture(self) -> Self {
         Self { stdout: OutputMode::Capture, stderr: OutputMode::Capture, ..self }
     }
 
     /// Capture stdout of the command, do not print it.
+    #[must_use]
     pub fn capture_stdout(self) -> Self {
         Self { stdout: OutputMode::Capture, ..self }
     }
-}
 
-/// This implementation exists to make it possible to pass both [BootstrapCommand] and
-/// `&mut BootstrapCommand` to `Build.run()`.
-impl AsMut<BootstrapCommand> for BootstrapCommand {
-    fn as_mut(&mut self) -> &mut BootstrapCommand {
-        self
+    /// Run the command, returning its output.
+    pub fn run(&mut self, builder: &Build) -> CommandOutput {
+        builder.run(self)
     }
 }
 
@@ -164,6 +167,13 @@ enum CommandStatus {
     DidNotStart,
 }
 
+/// Create a new BootstrapCommand. This is a helper function to make command creation
+/// shorter than `BootstrapCommand::new`.
+#[must_use]
+pub fn command<S: AsRef<OsStr>>(program: S) -> BootstrapCommand {
+    BootstrapCommand::new(program)
+}
+
 /// Represents the output of an executed process.
 #[allow(unused)]
 pub struct CommandOutput {
@@ -173,10 +183,12 @@ pub struct CommandOutput {
 }
 
 impl CommandOutput {
+    #[must_use]
     pub fn did_not_start() -> Self {
         Self { status: CommandStatus::DidNotStart, stdout: vec![], stderr: vec![] }
     }
 
+    #[must_use]
     pub fn is_success(&self) -> bool {
         match self.status {
             CommandStatus::Finished(status) => status.success(),
@@ -184,10 +196,12 @@ impl CommandOutput {
         }
     }
 
+    #[must_use]
     pub fn is_failure(&self) -> bool {
         !self.is_success()
     }
 
+    #[must_use]
     pub fn status(&self) -> Option<ExitStatus> {
         match self.status {
             CommandStatus::Finished(status) => Some(status),
@@ -195,14 +209,17 @@ impl CommandOutput {
         }
     }
 
+    #[must_use]
     pub fn stdout(&self) -> String {
         String::from_utf8(self.stdout.clone()).expect("Cannot parse process stdout as UTF-8")
     }
 
+    #[must_use]
     pub fn stdout_if_ok(&self) -> Option<String> {
         if self.is_success() { Some(self.stdout()) } else { None }
     }
 
+    #[must_use]
     pub fn stderr(&self) -> String {
         String::from_utf8(self.stderr.clone()).expect("Cannot parse process stderr as UTF-8")
     }
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 2575b7939b4..5dd3ba96786 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -47,7 +47,7 @@ macro_rules! t {
         }
     };
 }
-use crate::utils::exec::BootstrapCommand;
+use crate::utils::exec::{command, BootstrapCommand};
 pub use t;
 
 pub fn exe(name: &str, target: TargetSelection) -> String {
@@ -369,9 +369,9 @@ fn lld_flag_no_threads(builder: &Builder<'_>, lld_mode: LldMode, is_windows: boo
     let (windows_flag, other_flag) = LLD_NO_THREADS.get_or_init(|| {
         let newer_version = match lld_mode {
             LldMode::External => {
-                let mut cmd = BootstrapCommand::new("lld").capture_stdout();
+                let mut cmd = command("lld").capture_stdout();
                 cmd.arg("-flavor").arg("ld").arg("--version");
-                let out = builder.run(cmd).stdout();
+                let out = cmd.run(builder).stdout();
                 match (out.find(char::is_numeric), out.find('.')) {
                     (Some(b), Some(e)) => out.as_str()[b..e].parse::<i32>().ok().unwrap_or(14) > 10,
                     _ => true,
@@ -499,10 +499,10 @@ pub fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
 /// Whenever a git invocation is needed, this function should be preferred over
 /// manually building a git `BootstrapCommand`. This approach allows us to manage
 /// bootstrap-specific needs/hacks from a single source, rather than applying them on next to every
-/// `BootstrapCommand::new("git")`, which is painful to ensure that the required change is applied
+/// git command creation, which is painful to ensure that the required change is applied
 /// on each one of them correctly.
 pub fn git(source_dir: Option<&Path>) -> BootstrapCommand {
-    let mut git = BootstrapCommand::new("git");
+    let mut git = command("git");
 
     if let Some(source_dir) = source_dir {
         git.current_dir(source_dir);
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index 1a35dc1fd38..4f0104e4bba 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -379,7 +379,7 @@ impl<'a> Tarball<'a> {
             cmd.args(["--override-file-mtime", timestamp.trim()]);
         }
 
-        self.builder.run(cmd);
+        cmd.run(self.builder);
 
         // Ensure there are no symbolic links in the tarball. In particular,
         // rustup-toolchain-install-master and most versions of Windows can't handle symbolic links.
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
index 2b3d15e93c8..c3eda26ca8e 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
@@ -107,7 +107,7 @@ flag, for example:
 
 Users need to install or built wasi-sdk since release 20.0
 https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20
-and specify path to *wasi-root* `.cargo/config.toml`
+and specify path to *wasi-root* `config.toml`
 
 ```toml
 [target.wasm32-wasip1-threads]
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index a0ab262bf0b..86af38f3ee7 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -3293,10 +3293,9 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
         // call after consuming `{`
         decodeList() {
-            const cb = "}".charCodeAt(0);
             let c = this.string.charCodeAt(this.offset);
             const ret = [];
-            while (c !== cb) {
+            while (c !== 125) { // 125 = "}"
                 ret.push(this.decode());
                 c = this.string.charCodeAt(this.offset);
             }
@@ -3305,14 +3304,13 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
         // consumes and returns a list or integer
         decode() {
-            const [ob, la] = ["{", "`"].map(c => c.charCodeAt(0));
             let n = 0;
             let c = this.string.charCodeAt(this.offset);
-            if (c === ob) {
+            if (c === 123) { // 123 = "{"
                 this.offset += 1;
                 return this.decodeList();
             }
-            while (c < la) {
+            while (c < 96) { // 96 = "`"
                 n = (n << 4) | (c & 0xF);
                 this.offset += 1;
                 c = this.string.charCodeAt(this.offset);
@@ -3325,15 +3323,14 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
         next() {
             const c = this.string.charCodeAt(this.offset);
-            const [zero, ua, la] = ["0", "@", "`"].map(c => c.charCodeAt(0));
             // sixteen characters after "0" are backref
-            if (c >= zero && c < ua) {
+            if (c >= 48 && c < 64) { // 48 = "0", 64 = "@"
                 this.offset += 1;
-                return this.backrefQueue[c - zero];
+                return this.backrefQueue[c - 48];
             }
             // special exception: 0 doesn't use backref encoding
             // it's already one character, and it's always nullish
-            if (c === la) {
+            if (c === 96) { // 96 = "`"
                 this.offset += 1;
                 return this.cons(0);
             }
@@ -3472,7 +3469,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         searchIndex = [];
         searchIndexDeprecated = new Map();
         searchIndexEmptyDesc = new Map();
-        const charA = "A".charCodeAt(0);
         let currentIndex = 0;
         let id = 0;
 
@@ -3639,7 +3635,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                 // object defined above.
                 const row = {
                     crate,
-                    ty: itemTypes.charCodeAt(i) - charA,
+                    ty: itemTypes.charCodeAt(i) - 65, // 65 = "A"
                     name: itemNames[i],
                     path,
                     descShard,
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject a515d463427b3912ec0365d106791f88c1c14e1
+Subproject 154fdac39ae9629954e19e9986fd2cf2cdd8d96
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index 3e0bdc1c6f6..24fa88af82e 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -87,9 +87,7 @@ impl Diff {
         self
     }
 
-    #[track_caller]
-    pub fn run(&mut self) {
-        self.drop_bomb.defuse();
+    fn run_common(&self) -> (&str, &str, String, String) {
         let expected = self.expected.as_ref().expect("expected text not set");
         let mut actual = self.actual.as_ref().expect("actual text not set").to_string();
         let expected_name = self.expected_name.as_ref().unwrap();
@@ -104,6 +102,14 @@ impl Diff {
             .header(expected_name, actual_name)
             .to_string();
 
+        (expected_name, actual_name, output, actual)
+    }
+
+    #[track_caller]
+    pub fn run(&mut self) {
+        self.drop_bomb.defuse();
+        let (expected_name, actual_name, output, actual) = self.run_common();
+
         if !output.is_empty() {
             // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
             // environment variable set), then we write into the file and return.
@@ -120,4 +126,26 @@ impl Diff {
             )
         }
     }
+
+    #[track_caller]
+    pub fn run_fail(&mut self) {
+        self.drop_bomb.defuse();
+        let (expected_name, actual_name, output, actual) = self.run_common();
+
+        if output.is_empty() {
+            // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
+            // environment variable set), then we write into the file and return.
+            if let Some(ref expected_file) = self.expected_file {
+                if std::env::var("RUSTC_BLESS_TEST").is_ok() {
+                    println!("Blessing `{}`", expected_file.display());
+                    fs_wrapper::write(expected_file, actual);
+                    return;
+                }
+            }
+            panic!(
+                "test failed: `{}` is not different from `{}`\n\n{}",
+                expected_name, actual_name, output
+            )
+        }
+    }
 }
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index ff98bd538db..31cb32d349a 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -23,8 +23,6 @@ run-make/dep-info-spaces/Makefile
 run-make/dep-info/Makefile
 run-make/dump-ice-to-disk/Makefile
 run-make/dump-mono-stats/Makefile
-run-make/emit-path-unhashed/Makefile
-run-make/emit-shared-files/Makefile
 run-make/emit-to-stdout/Makefile
 run-make/env-dep-info/Makefile
 run-make/export-executable-symbols/Makefile
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 7e5656926ab..2f8abc77566 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -45,6 +45,8 @@ const EXCEPTION_PATHS: &[&str] = &[
     // pointer regardless of the target architecture. As a result,
     // we must use `#[cfg(windows)]` to conditionally compile the
     // correct `VaList` structure for windows.
+    "library/core/src/ffi/va_list.rs",
+    // We placed a linkage against Windows libraries here
     "library/core/src/ffi/mod.rs",
     "library/std/src/sys", // Platform-specific code for std lives here.
     "library/std/src/os",  // Platform-specific public interfaces
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index e4d54d2a2b5..8e693c35adc 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -110,6 +110,7 @@ const ROOT_PROBLEMATIC_CONSTS: &[u32] = &[
     173390526, 721077,
 ];
 
+// Returns all permutations of problematic consts, over 2000 elements.
 fn generate_problematic_strings(
     consts: &[u32],
     letter_digit: &FxHashMap<char, char>,
@@ -319,6 +320,8 @@ pub fn check(path: &Path, bad: &mut bool) {
         ROOT_PROBLEMATIC_CONSTS,
         &[('A', '4'), ('B', '8'), ('E', '3')].iter().cloned().collect(),
     );
+    // This creates a RegexSet as regex contains performance optimizations to be able to deal with these over
+    // 2000 needles efficiently. This runs over the entire source code, so performance matters.
     let problematic_regex = RegexSet::new(problematic_consts_strings.as_slice()).unwrap();
 
     walk(path, skip, &mut |entry, contents| {
diff --git a/tests/crashes/125099.rs b/tests/crashes/125099.rs
deleted file mode 100644
index bfc8c8fdcf6..00000000000
--- a/tests/crashes/125099.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: rust-lang/rust#125099
-
-pub trait ContFn<T>: Fn(T) -> Self::Future {
-    type Future;
-}
-impl<T, F> ContFn<T> for F
-where
-    F: Fn(T),
-{
-    type Future = ();
-}
-
-pub trait SeqHandler {
-    type Requires;
-    fn process<F: ContFn<Self::Requires>>() -> impl Sized;
-}
-
-pub struct ConvertToU64;
-impl SeqHandler for ConvertToU64 {
-    type Requires = u64;
-    fn process<F: ContFn<Self::Requires>>() -> impl Sized {}
-}
-
-fn main() {}
diff --git a/tests/crashes/127332.rs b/tests/crashes/127332.rs
deleted file mode 100644
index 5c14af01cec..00000000000
--- a/tests/crashes/127332.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: rust-lang/rust #127332
-
-async fn fun() {
-    enum Foo {
-        A { x: u32 },
-    }
-    let orig = Foo::A { x: 5 };
-    Foo::A { x: 6, ..orig };
-}
diff --git a/tests/run-make/emit-path-unhashed/Makefile b/tests/run-make/emit-path-unhashed/Makefile
deleted file mode 100644
index 611f8578140..00000000000
--- a/tests/run-make/emit-path-unhashed/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-include ../tools.mk
-
-OUT=$(TMPDIR)/emit
-
-# --emit KIND=PATH should not affect crate hash vs --emit KIND
-all: $(OUT)/a/libfoo.rlib $(OUT)/b/libfoo.rlib $(OUT)/c/libfoo.rlib \
-		$(TMPDIR)/libfoo.rlib
-	$(RUSTC) -Zls=root $(TMPDIR)/libfoo.rlib > $(TMPDIR)/base.txt
-	$(RUSTC) -Zls=root $(OUT)/a/libfoo.rlib > $(TMPDIR)/a.txt
-	$(RUSTC) -Zls=root $(OUT)/b/libfoo.rlib > $(TMPDIR)/b.txt
-	$(RUSTC) -Zls=root $(OUT)/c/libfoo.rlib > $(TMPDIR)/c.txt
-
-	diff $(TMPDIR)/base.txt $(TMPDIR)/a.txt
-	diff $(TMPDIR)/base.txt $(TMPDIR)/b.txt
-
-	# Different KIND parameters do affect hash.
-	# diff exits 1 on difference, 2 on trouble
-	diff $(TMPDIR)/base.txt $(TMPDIR)/c.txt ; test "$$?" -eq 1
-
-# Default output name
-$(TMPDIR)/libfoo.rlib: foo.rs
-	$(RUSTC) --emit link foo.rs
-
-# Output named with -o
-$(OUT)/a/libfoo.rlib: foo.rs
-	mkdir -p $(OUT)/a
-	$(RUSTC) --emit link -o $@ foo.rs
-
-# Output named with KIND=PATH
-$(OUT)/b/libfoo.rlib: foo.rs
-	mkdir -p $(OUT)/b
-	$(RUSTC) --emit link=$@ foo.rs
-
-# Output multiple kinds
-$(OUT)/c/libfoo.rlib: foo.rs
-	mkdir -p $(OUT)/c
-	$(RUSTC) --emit link=$@,metadata foo.rs
diff --git a/tests/run-make/emit-path-unhashed/rmake.rs b/tests/run-make/emit-path-unhashed/rmake.rs
new file mode 100644
index 00000000000..ce56c197588
--- /dev/null
+++ b/tests/run-make/emit-path-unhashed/rmake.rs
@@ -0,0 +1,34 @@
+// Specifying how rustc outputs a file can be done in different ways, such as
+// the output flag or the KIND=NAME syntax. However, some of these methods used
+// to result in different hashes on output files even though they yielded the
+// exact same result otherwise. This was fixed in #86045, and this test checks
+// that the hash is only modified when the output is made different, such as by
+// adding a new output type (in this test, metadata).
+// See https://github.com/rust-lang/rust/issues/86044
+
+use run_make_support::{diff, fs_wrapper, rustc};
+
+fn main() {
+    fs_wrapper::create_dir("emit");
+    fs_wrapper::create_dir("emit/a");
+    fs_wrapper::create_dir("emit/b");
+    fs_wrapper::create_dir("emit/c");
+    // The default output name.
+    rustc().emit("link").input("foo.rs").run();
+    // The output is named with the output flag.
+    rustc().emit("link").output("emit/a/libfoo.rlib").input("foo.rs").run();
+    // The output is named with link=NAME.
+    rustc().emit("link=emit/b/libfoo.rlib").input("foo.rs").run();
+    // The output is named with link=NAME, with an additional kind tacked on.
+    rustc().emit("link=emit/c/libfoo.rlib,metadata").input("foo.rs").run();
+
+    let base = rustc().arg("-Zls=root").input("libfoo.rlib").run().stdout_utf8();
+    let a = rustc().arg("-Zls=root").input("emit/a/libfoo.rlib").run().stdout_utf8();
+    let b = rustc().arg("-Zls=root").input("emit/b/libfoo.rlib").run().stdout_utf8();
+    let c = rustc().arg("-Zls=root").input("emit/c/libfoo.rlib").run().stdout_utf8();
+    // Both the output flag and link=NAME methods do not modify the hash of the output file.
+    diff().expected_text("base", &base).actual_text("a", a).run();
+    diff().expected_text("base", &base).actual_text("b", b).run();
+    // However, having multiple types of outputs does modify the hash.
+    diff().expected_text("base", &base).actual_text("c", c).run_fail();
+}
diff --git a/tests/run-make/emit-shared-files/Makefile b/tests/run-make/emit-shared-files/Makefile
deleted file mode 100644
index 27c72b00368..00000000000
--- a/tests/run-make/emit-shared-files/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-include ../tools.mk
-
-INVOCATION_ONLY = $(TMPDIR)/invocation-only
-TOOLCHAIN_ONLY = $(TMPDIR)/toolchain-only
-ALL_SHARED = $(TMPDIR)/all-shared
-
-all: invocation-only toolchain-only all-shared
-
-invocation-only:
-	$(RUSTDOC) -Z unstable-options --emit=invocation-specific --output $(INVOCATION_ONLY) --resource-suffix=-xxx --theme y.css --extend-css z.css x.rs
-	[ -e $(INVOCATION_ONLY)/search-index-xxx.js ]
-	[ -e $(INVOCATION_ONLY)/settings.html ]
-	[ -e $(INVOCATION_ONLY)/x/all.html ]
-	[ -e $(INVOCATION_ONLY)/x/index.html ]
-	[ -e $(INVOCATION_ONLY)/theme-xxx.css ] # generated from z.css
-	! [ -e $(INVOCATION_ONLY)/storage-xxx.js ]
-	! [ -e $(INVOCATION_ONLY)/SourceSerif4-It.ttf.woff2 ]
-
-	# FIXME: this probably shouldn't have a suffix
-	[ -e $(INVOCATION_ONLY)/y-xxx.css ]
-	# FIXME: this is technically incorrect (see `write_shared`)
-	! [ -e $(INVOCATION_ONLY)/main-xxx.js ]
-
-toolchain-only:
-	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources --output $(TOOLCHAIN_ONLY) --resource-suffix=-xxx --extend-css z.css x.rs
-	[ -e $(TOOLCHAIN_ONLY)/static.files/storage-*.js ]
-	[ -e $(TOOLCHAIN_ONLY)/static.files/SourceSerif4-It-*.ttf.woff2 ]
-	! [ -e $(TOOLCHAIN_ONLY)/search-index-xxx.js ]
-	! [ -e $(TOOLCHAIN_ONLY)/x/index.html ]
-	! [ -e $(TOOLCHAIN_ONLY)/theme.css ]
-
-	[ -e $(TOOLCHAIN_ONLY)/static.files/main-*.js ]
-	! [ -e $(TOOLCHAIN_ONLY)/y-xxx.css ]
-
-all-shared:
-	$(RUSTDOC) -Z unstable-options --emit=toolchain-shared-resources,unversioned-shared-resources --output $(ALL_SHARED) --resource-suffix=-xxx --extend-css z.css x.rs
-	[ -e $(ALL_SHARED)/static.files/storage-*.js ]
-	[ -e $(ALL_SHARED)/static.files/SourceSerif4-It-*.ttf.woff2 ]
-	! [ -e $(ALL_SHARED)/search-index-xxx.js ]
-	! [ -e $(ALL_SHARED)/settings.html ]
-	! [ -e $(ALL_SHARED)/x ]
-	! [ -e $(ALL_SHARED)/src ]
-	! [ -e $(ALL_SHARED)/theme.css ]
-
-	[ -e $(ALL_SHARED)/static.files/main-*.js ]
-	! [ -e $(ALL_SHARED)/y-xxx.css ]
diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs
new file mode 100644
index 00000000000..33c12310246
--- /dev/null
+++ b/tests/run-make/emit-shared-files/rmake.rs
@@ -0,0 +1,102 @@
+// This test checks the functionality of one of rustdoc's unstable options,
+// the ability to specify emit restrictions with `--emit`.
+// `invocation-only` should only emit crate-specific files.
+// `toolchain-only` should only emit toolchain-specific files.
+// `all-shared` should only emit files that can be shared between crates.
+// See https://github.com/rust-lang/rust/pull/83478
+
+use run_make_support::{has_extension, has_prefix, rustdoc, shallow_find_files};
+use std::path::Path;
+
+fn main() {
+    rustdoc()
+        .arg("-Zunstable-options")
+        .arg("--emit=invocation-specific")
+        .output("invocation-only")
+        .arg("--resource-suffix=-xxx")
+        .args(&["--theme", "y.css"])
+        .args(&["--extend-css", "z.css"])
+        .input("x.rs")
+        .run();
+    assert!(Path::new("invocation-only/search-index-xxx.js").exists());
+    assert!(Path::new("invocation-only/settings.html").exists());
+    assert!(Path::new("invocation-only/x/all.html").exists());
+    assert!(Path::new("invocation-only/x/index.html").exists());
+    assert!(Path::new("invocation-only/theme-xxx.css").exists()); // generated from z.css
+    assert!(!Path::new("invocation-only/storage-xxx.js").exists());
+    assert!(!Path::new("invocation-only/SourceSerif4-It.ttf.woff2").exists());
+    // FIXME: this probably shouldn't have a suffix
+    assert!(Path::new("invocation-only/y-xxx.css").exists());
+    // FIXME: this is technically incorrect (see `write_shared`)
+    assert!(!Path::new("invocation-only/main-xxx.js").exists());
+
+    rustdoc()
+        .arg("-Zunstable-options")
+        .arg("--emit=toolchain-shared-resources")
+        .output("toolchain-only")
+        .arg("--resource-suffix=-xxx")
+        .args(&["--extend-css", "z.css"])
+        .input("x.rs")
+        .run();
+    assert_eq!(
+        shallow_find_files("toolchain-only/static.files", |path| {
+            has_prefix(path, "storage-") && has_extension(path, "js")
+        })
+        .len(),
+        1
+    );
+    assert_eq!(
+        shallow_find_files("toolchain-only/static.files", |path| {
+            has_prefix(path, "SourceSerif4-It-") && has_extension(path, "woff2")
+        })
+        .len(),
+        1
+    );
+    assert_eq!(
+        shallow_find_files("toolchain-only/static.files", |path| {
+            has_prefix(path, "main-") && has_extension(path, "js")
+        })
+        .len(),
+        1
+    );
+    assert!(!Path::new("toolchain-only/search-index-xxx.js").exists());
+    assert!(!Path::new("toolchain-only/x/index.html").exists());
+    assert!(!Path::new("toolchain-only/theme.css").exists());
+    assert!(!Path::new("toolchain-only/y-xxx.css").exists());
+
+    rustdoc()
+        .arg("-Zunstable-options")
+        .arg("--emit=toolchain-shared-resources,unversioned-shared-resources")
+        .output("all-shared")
+        .arg("--resource-suffix=-xxx")
+        .args(&["--extend-css", "z.css"])
+        .input("x.rs")
+        .run();
+    assert_eq!(
+        shallow_find_files("all-shared/static.files", |path| {
+            has_prefix(path, "storage-") && has_extension(path, "js")
+        })
+        .len(),
+        1
+    );
+    assert_eq!(
+        shallow_find_files("all-shared/static.files", |path| {
+            has_prefix(path, "SourceSerif4-It-") && has_extension(path, "woff2")
+        })
+        .len(),
+        1
+    );
+    assert!(!Path::new("all-shared/search-index-xxx.js").exists());
+    assert!(!Path::new("all-shared/settings.html").exists());
+    assert!(!Path::new("all-shared/x").exists());
+    assert!(!Path::new("all-shared/src").exists());
+    assert!(!Path::new("all-shared/theme.css").exists());
+    assert_eq!(
+        shallow_find_files("all-shared/static.files", |path| {
+            has_prefix(path, "main-") && has_extension(path, "js")
+        })
+        .len(),
+        1
+    );
+    assert!(!Path::new("all-shared/y-xxx.css").exists());
+}
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
index 3cc35b21409..b547da7126a 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -1,29 +1,29 @@
-error[E0311]: the parameter type `U` may not live long enough
+error[E0311]: the parameter type `T` may not live long enough
   --> $DIR/async-generics-and-bounds.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |     ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |            |
-   |     |            the parameter type `U` must be valid for the anonymous lifetime as defined here...
+   |     |            the parameter type `T` must be valid for the anonymous lifetime as defined here...
    |     ...so that the reference type `&(T, U)` does not outlive the data it points at
    |
 help: consider adding an explicit lifetime bound
    |
-LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, U: 'a;
+LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, T: 'a;
    |                 ++++  ++           ++                                       +++++++
 
-error[E0311]: the parameter type `T` may not live long enough
+error[E0311]: the parameter type `U` may not live long enough
   --> $DIR/async-generics-and-bounds.rs:9:5
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |     ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     |            |
-   |     |            the parameter type `T` must be valid for the anonymous lifetime as defined here...
+   |     |            the parameter type `U` must be valid for the anonymous lifetime as defined here...
    |     ...so that the reference type `&(T, U)` does not outlive the data it points at
    |
 help: consider adding an explicit lifetime bound
    |
-LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, T: 'a;
+LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, U: 'a;
    |                 ++++  ++           ++                                       +++++++
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr
index 3b27f8fe2f0..2e29a9bcc77 100644
--- a/tests/ui/async-await/in-trait/async-generics.stderr
+++ b/tests/ui/async-await/in-trait/async-generics.stderr
@@ -1,29 +1,29 @@
-error[E0311]: the parameter type `U` may not live long enough
+error[E0311]: the parameter type `T` may not live long enough
   --> $DIR/async-generics.rs:6:5
    |
 LL |     async fn foo(&self) -> &(T, U);
    |     ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^
    |     |            |
-   |     |            the parameter type `U` must be valid for the anonymous lifetime as defined here...
+   |     |            the parameter type `T` must be valid for the anonymous lifetime as defined here...
    |     ...so that the reference type `&(T, U)` does not outlive the data it points at
    |
 help: consider adding an explicit lifetime bound
    |
-LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a;
+LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: 'a;
    |                 ++++  ++           ++        +++++++++++
 
-error[E0311]: the parameter type `T` may not live long enough
+error[E0311]: the parameter type `U` may not live long enough
   --> $DIR/async-generics.rs:6:5
    |
 LL |     async fn foo(&self) -> &(T, U);
    |     ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^
    |     |            |
-   |     |            the parameter type `T` must be valid for the anonymous lifetime as defined here...
+   |     |            the parameter type `U` must be valid for the anonymous lifetime as defined here...
    |     ...so that the reference type `&(T, U)` does not outlive the data it points at
    |
 help: consider adding an explicit lifetime bound
    |
-LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where T: 'a;
+LL |     async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a;
    |                 ++++  ++           ++        +++++++++++
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr
index 29ebbc5dffb..a3a31f43447 100644
--- a/tests/ui/compare-method/bad-self-type.stderr
+++ b/tests/ui/compare-method/bad-self-type.stderr
@@ -41,7 +41,7 @@ note: type in trait
 LL |     fn bar(self) -> Option<()>;
    |                     ^^^^^^^^^^
    = note: expected signature `fn(MyFuture) -> Option<()>`
-              found signature `fn(MyFuture)`
+              found signature `fn(MyFuture) -> ()`
 help: change the output type to match the trait
    |
 LL |     fn bar(self) -> Option<()> {}
diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs
index 57767e96596..e71f88b8d5f 100644
--- a/tests/ui/consts/offset_from_ub.rs
+++ b/tests/ui/consts/offset_from_ub.rs
@@ -92,6 +92,14 @@ pub const TOO_FAR_APART2: isize = {
     unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
     //~| too far before
 };
+pub const TOO_FAR_APART3: isize = {
+    let ptr1 = &0u8 as *const u8;
+    let ptr2 = ptr1.wrapping_offset(isize::MIN);
+    // The result of this would be `isize::MIN`, which *does* fit in an `isize`, but its
+    // absolute value does not. (Also anyway there cannot be an allocation of that size.)
+    unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
+    //~| too far before
+};
 
 const WRONG_ORDER_UNSIGNED: usize = {
     let a = ['a', 'b', 'c'];
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 65f75a6e058..7caf6247b9e 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -60,13 +60,19 @@ LL |     unsafe { ptr_offset_from(ptr1, ptr2) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:99:14
+  --> $DIR/offset_from_ub.rs:100:14
+   |
+LL |     unsafe { ptr_offset_from(ptr1, ptr2) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:107:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:106:14
+  --> $DIR/offset_from_ub.rs:114:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second
@@ -79,7 +85,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OFFSET_VERY_FAR1`
-  --> $DIR/offset_from_ub.rs:115:14
+  --> $DIR/offset_from_ub.rs:123:14
    |
 LL |     unsafe { ptr2.offset_from(ptr1) }
    |              ^^^^^^^^^^^^^^^^^^^^^^
@@ -92,11 +98,11 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OFFSET_VERY_FAR2`
-  --> $DIR/offset_from_ub.rs:121:14
+  --> $DIR/offset_from_ub.rs:129:14
    |
 LL |     unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr
index bc6c5a632a1..709b3119276 100644
--- a/tests/ui/error-codes/E0308.stderr
+++ b/tests/ui/error-codes/E0308.stderr
@@ -5,7 +5,7 @@ LL |     fn size_of<T>();
    |                    ^ expected `usize`, found `()`
    |
    = note: expected signature `extern "rust-intrinsic" fn() -> usize`
-              found signature `extern "rust-intrinsic" fn()`
+              found signature `extern "rust-intrinsic" fn() -> ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index 06a606b09dc..584724dfe59 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -92,7 +92,7 @@ LL |     extern "rust-call" fn call(self, args: ()) -> () {}
    |                                ^^^^ expected `&Foo`, found `Foo`
    |
    = note: expected signature `extern "rust-call" fn(&Foo, ()) -> _`
-              found signature `extern "rust-call" fn(Foo, ())`
+              found signature `extern "rust-call" fn(Foo, ()) -> ()`
 help: change the self-receiver type to match the trait
    |
 LL |     extern "rust-call" fn call(&self, args: ()) -> () {}
@@ -162,7 +162,7 @@ LL |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
    |                                    ^^^^^ types differ in mutability
    |
    = note: expected signature `extern "rust-call" fn(&mut Bar, ()) -> _`
-              found signature `extern "rust-call" fn(&Bar, ())`
+              found signature `extern "rust-call" fn(&Bar, ()) -> ()`
 help: change the self-receiver type to match the trait
    |
 LL |     extern "rust-call" fn call_mut(&mut self, args: ()) -> () {}
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
index 0b3331b040d..5000601e90f 100644
--- a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
+++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
@@ -10,7 +10,7 @@ LL |     x = foo::<()>;
    |         ^^^^^^^^^ expected fn item, found a different fn item
    |
    = note: expected fn item `fn(F) -> F {bar::<F>}`
-              found fn item `fn(()) {foo::<()>}`
+              found fn item `fn(()) -> () {foo::<()>}`
 
 error[E0308]: mismatched types
   --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9
@@ -26,7 +26,7 @@ LL |     let mut x = bar::<()>;
 LL |     x = foo::<I>;
    |         ^^^^^^^^ expected fn item, found a different fn item
    |
-   = note: expected fn item `fn(()) {bar::<()>}`
+   = note: expected fn item `fn(()) -> () {bar::<()>}`
               found fn item `fn(I) -> I {foo::<I>}`
 help: use parentheses to call this function
    |
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
index 9b5d84b5b09..c5c4f2c4d23 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `i32: Baz<Self>` is not satisfied
+error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
   --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
    |
 LL |     type Bar<T>: Baz<Self> = i32;
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
index e32c59a75c6..75cbe43eeb4 100644
--- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
@@ -35,7 +35,7 @@ note: type in trait
 LL |         fn method() -> Self::Ty;
    |                        ^^^^^^^^
    = note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
-              found signature `fn()`
+              found signature `fn() -> ()`
 note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/in-assoc-type-unconstrained.rs:22:12
    |
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
new file mode 100644
index 00000000000..d71c1768a6a
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr
@@ -0,0 +1,173 @@
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:36:5
+   |
+LL | /     fn autobatch<F>(self) -> impl Trait
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     where
+LL | |         F: Callback<Self::CallbackArg>,
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:36:30
+   |
+LL |     fn autobatch<F>(self) -> impl Trait
+   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: required by a bound in `<Sender as ChannelSender>::autobatch`
+  --> $DIR/false-positive-predicate-entailment-error.rs:43:12
+   |
+LL |     fn autobatch<F>(self) -> impl Trait
+   |        --------- required by a bound in this associated function
+...
+LL |         F: Callback<Self::CallbackArg>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<Sender as ChannelSender>::autobatch`
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:36:5
+   |
+LL | /     fn autobatch<F>(self) -> impl Trait
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     where
+LL | |         F: Callback<Self::CallbackArg>,
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:43:12
+   |
+LL |         F: Callback<Self::CallbackArg>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+note: the requirement `F: Callback<i32>` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method
+  --> $DIR/false-positive-predicate-entailment-error.rs:25:8
+   |
+LL | trait ChannelSender {
+   |       ------------- in this trait
+...
+LL |     fn autobatch<F>(self) -> impl Trait
+   |        ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback<i32>`
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:36:30
+   |
+LL |     fn autobatch<F>(self) -> impl Trait
+   |                              ^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `F: Callback<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:27:12
+   |
+LL |         F: Callback<Self::CallbackArg>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:36:5
+   |
+LL | /     fn autobatch<F>(self) -> impl Trait
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     where
+LL | |         F: Callback<Self::CallbackArg>,
+   | |_______________________________________^ the trait `MyFn<i32>` is not implemented for `F`, which is required by `F: Callback<i32>`
+   |
+note: required for `F` to implement `Callback<i32>`
+  --> $DIR/false-positive-predicate-entailment-error.rs:14:21
+   |
+LL | impl<A, F: MyFn<A>> Callback<A> for F {
+   |            -------  ^^^^^^^^^^^     ^
+   |            |
+   |            unsatisfied trait bound introduced here
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error[E0277]: the trait bound `F: MyFn<i32>` is not satisfied
+  --> $DIR/false-positive-predicate-entailment-error.rs:43:12
+   |
+LL |         F: Callback<Self::CallbackArg>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn<i32>` is not implemented for `F`
+   |
+note: required by a bound in `Callback`
+  --> $DIR/false-positive-predicate-entailment-error.rs:10:20
+   |
+LL | trait Callback<A>: MyFn<A, Output = Self::Ret> {
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Callback`
+help: consider further restricting this bound
+   |
+LL |         F: Callback<Self::CallbackArg> + MyFn<i32>,
+   |                                        +++++++++++
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs
new file mode 100644
index 00000000000..59fdeab9e0a
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs
@@ -0,0 +1,51 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+trait MyFn<T> {
+    type Output;
+}
+
+trait Callback<A>: MyFn<A, Output = Self::Ret> {
+    type Ret;
+}
+
+impl<A, F: MyFn<A>> Callback<A> for F {
+    type Ret = F::Output;
+}
+
+struct Thing;
+trait Trait {}
+impl Trait for Thing {}
+
+trait ChannelSender {
+    type CallbackArg;
+
+    fn autobatch<F>(self) -> impl Trait
+    where
+        F: Callback<Self::CallbackArg>;
+        //[current]~^ ERROR the trait bound `F: Callback<i32>` is not satisfied
+}
+
+struct Sender;
+
+impl ChannelSender for Sender {
+    type CallbackArg = i32;
+
+    fn autobatch<F>(self) -> impl Trait
+    //[current]~^ ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    //[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    //[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    //[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    //[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    where
+        F: Callback<Self::CallbackArg>,
+        //[current]~^ ERROR the trait bound `F: Callback<i32>` is not satisfied
+        //[current]~| ERROR the trait bound `F: MyFn<i32>` is not satisfied
+    {
+        Thing
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs
index 502b2af2bc6..760102794c3 100644
--- a/tests/ui/impl-trait/nested_impl_trait.rs
+++ b/tests/ui/impl-trait/nested_impl_trait.rs
@@ -5,7 +5,7 @@ fn fine(x: impl Into<u32>) -> impl Into<u32> { x }
 
 fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
 //~^ ERROR nested `impl Trait` is not allowed
-//~| ERROR the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
+//~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
 
 fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
 //~^ ERROR nested `impl Trait` is not allowed
@@ -18,7 +18,7 @@ struct X;
 impl X {
     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
     //~^ ERROR nested `impl Trait` is not allowed
-    //~| ERROR the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
+    //~| ERROR the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
 }
 
 fn allowed_in_assoc_type() -> impl Iterator<Item=impl Fn()> {
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index a53312e5c0b..83d1347aff4 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -42,7 +42,7 @@ LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
+error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
   --> $DIR/nested_impl_trait.rs:6:46
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
@@ -51,7 +51,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    = help: the trait `Into<U>` is implemented for `T`
    = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
 
-error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
+error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
   --> $DIR/nested_impl_trait.rs:19:34
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
diff --git a/tests/ui/impl-trait/trait_type.stderr b/tests/ui/impl-trait/trait_type.stderr
index 0eb132c7a19..989779a6178 100644
--- a/tests/ui/impl-trait/trait_type.stderr
+++ b/tests/ui/impl-trait/trait_type.stderr
@@ -5,7 +5,7 @@ LL |    fn fmt(&self, x: &str) -> () { }
    |                     ^^^^ types differ in mutability
    |
    = note: expected signature `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>`
-              found signature `fn(&MyType, &str)`
+              found signature `fn(&MyType, &str) -> ()`
 help: change the parameter type to match the trait
    |
 LL |    fn fmt(&self, x: &mut Formatter<'_>) -> () { }
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
index aa1b1b73bae..2672efe51c9 100644
--- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
@@ -5,7 +5,7 @@ LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpi
    |                                                                                   ^ expected `isize`, found `()`
    |
    = note: expected signature `fn(fn() -> _, _, _, _) -> isize`
-              found signature `fn(fn() -> _, _, _, _)`
+              found signature `fn(fn() -> _, _, _, _) -> ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
index e44eeffb01b..1acefa314aa 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/allowed-operations.rs
@@ -37,6 +37,16 @@ macro_rules! without_dollar_sign_is_an_ident {
     };
 }
 
+macro_rules! literals {
+    ($ident:ident) => {{
+        let ${concat(_a, "_b")}: () = ();
+        let ${concat("_b", _a)}: () = ();
+
+        let ${concat($ident, "_b")}: () = ();
+        let ${concat("_b", $ident)}: () = ();
+    }};
+}
+
 fn main() {
     create_things!(behold);
     behold_separated_idents_in_a_fn();
@@ -55,4 +65,6 @@ fn main() {
     without_dollar_sign_is_an_ident!(_123);
     assert_eq!(VARident, 1);
     assert_eq!(VAR_123, 2);
+
+    literals!(_hello);
 }
diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs
index f72b9baca89..b1cb2141cc4 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.rs
@@ -26,14 +26,14 @@ macro_rules! idents_11 {
 macro_rules! no_params {
     () => {
         let ${concat(r#abc, abc)}: () = ();
-        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~^ ERROR expected identifier or string literal
         //~| ERROR expected pattern, found `$`
 
         let ${concat(abc, r#abc)}: () = ();
-        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~^ ERROR expected identifier or string literal
 
         let ${concat(r#abc, r#abc)}: () = ();
-        //~^ ERROR `${concat(..)}` currently does not support raw identifiers
+        //~^ ERROR expected identifier or string literal
     };
 }
 
diff --git a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr
index dd525cf0801..4e11e20acc5 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr
+++ b/tests/ui/macros/macro-metavar-expr-concat/raw-identifiers.stderr
@@ -1,16 +1,16 @@
-error: `${concat(..)}` currently does not support raw identifiers
+error: expected identifier or string literal
   --> $DIR/raw-identifiers.rs:28:22
    |
 LL |         let ${concat(r#abc, abc)}: () = ();
    |                      ^^^^^
 
-error: `${concat(..)}` currently does not support raw identifiers
+error: expected identifier or string literal
   --> $DIR/raw-identifiers.rs:32:27
    |
 LL |         let ${concat(abc, r#abc)}: () = ();
    |                           ^^^^^
 
-error: `${concat(..)}` currently does not support raw identifiers
+error: expected identifier or string literal
   --> $DIR/raw-identifiers.rs:35:22
    |
 LL |         let ${concat(r#abc, r#abc)}: () = ();
diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
index bf47442ea76..b2845c8d1c1 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.rs
@@ -11,9 +11,6 @@ macro_rules! wrong_concat_declarations {
         ${concat(aaaa,)}
         //~^ ERROR expected identifier
 
-        ${concat(aaaa, 1)}
-        //~^ ERROR expected identifier
-
         ${concat(_, aaaa)}
 
         ${concat(aaaa aaaa)}
@@ -30,9 +27,6 @@ macro_rules! wrong_concat_declarations {
 
         ${concat($ex, aaaa,)}
         //~^ ERROR expected identifier
-
-        ${concat($ex, aaaa, 123)}
-        //~^ ERROR expected identifier
     };
 }
 
@@ -43,8 +37,80 @@ macro_rules! dollar_sign_without_referenced_ident {
     };
 }
 
+macro_rules! starting_number {
+    ($ident:ident) => {{
+        let ${concat("1", $ident)}: () = ();
+        //~^ ERROR `${concat(..)}` is not generating a valid identifier
+    }};
+}
+
+macro_rules! starting_valid_unicode {
+    ($ident:ident) => {{
+        let ${concat("Ý", $ident)}: () = ();
+    }};
+}
+
+macro_rules! starting_invalid_unicode {
+    ($ident:ident) => {{
+        let ${concat("\u{00BD}", $ident)}: () = ();
+        //~^ ERROR `${concat(..)}` is not generating a valid identifier
+    }};
+}
+
+macro_rules! ending_number {
+    ($ident:ident) => {{
+        let ${concat($ident, "1")}: () = ();
+    }};
+}
+
+macro_rules! ending_valid_unicode {
+    ($ident:ident) => {{
+        let ${concat($ident, "Ý")}: () = ();
+    }};
+}
+
+macro_rules! ending_invalid_unicode {
+    ($ident:ident) => {{
+        let ${concat($ident, "\u{00BD}")}: () = ();
+        //~^ ERROR `${concat(..)}` is not generating a valid identifier
+    }};
+}
+
+macro_rules! empty {
+    () => {{
+        let ${concat("", "")}: () = ();
+        //~^ ERROR `${concat(..)}` is not generating a valid identifier
+    }};
+}
+
+macro_rules! unsupported_literals {
+    ($ident:ident) => {{
+        let ${concat(_a, 'b')}: () = ();
+        //~^ ERROR expected identifier or string literal
+        //~| ERROR expected pattern
+        let ${concat(_a, 1)}: () = ();
+        //~^ ERROR expected identifier or string literal
+
+        let ${concat($ident, 'b')}: () = ();
+        //~^ ERROR expected identifier or string literal
+        let ${concat($ident, 1)}: () = ();
+        //~^ ERROR expected identifier or string literal
+    }};
+}
+
 fn main() {
     wrong_concat_declarations!(1);
 
     dollar_sign_without_referenced_ident!(VAR);
+
+    starting_number!(_abc);
+    starting_valid_unicode!(_abc);
+    starting_invalid_unicode!(_abc);
+
+    ending_number!(_abc);
+    ending_valid_unicode!(_abc);
+    ending_invalid_unicode!(_abc);
+    unsupported_literals!(_abc);
+
+    empty!();
 }
diff --git a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
index b216a86d59a..2fe5842b39e 100644
--- a/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
+++ b/tests/ui/macros/macro-metavar-expr-concat/syntax-errors.stderr
@@ -1,4 +1,4 @@
-error: expected identifier
+error: expected identifier or string literal
   --> $DIR/syntax-errors.rs:5:10
    |
 LL |         ${concat()}
@@ -10,59 +10,126 @@ error: `concat` must have at least two elements
 LL |         ${concat(aaaa)}
    |           ^^^^^^
 
-error: expected identifier
+error: expected identifier or string literal
   --> $DIR/syntax-errors.rs:11:10
    |
 LL |         ${concat(aaaa,)}
    |          ^^^^^^^^^^^^^^^
 
-error: expected identifier, found `1`
-  --> $DIR/syntax-errors.rs:14:24
-   |
-LL |         ${concat(aaaa, 1)}
-   |                        ^ help: try removing `1`
-
 error: expected comma
-  --> $DIR/syntax-errors.rs:19:10
+  --> $DIR/syntax-errors.rs:16:10
    |
 LL |         ${concat(aaaa aaaa)}
    |          ^^^^^^^^^^^^^^^^^^^
 
 error: `concat` must have at least two elements
-  --> $DIR/syntax-errors.rs:22:11
+  --> $DIR/syntax-errors.rs:19:11
    |
 LL |         ${concat($ex)}
    |           ^^^^^^
 
 error: expected comma
-  --> $DIR/syntax-errors.rs:28:10
+  --> $DIR/syntax-errors.rs:25:10
    |
 LL |         ${concat($ex, aaaa 123)}
    |          ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: expected identifier
-  --> $DIR/syntax-errors.rs:31:10
+error: expected identifier or string literal
+  --> $DIR/syntax-errors.rs:28:10
    |
 LL |         ${concat($ex, aaaa,)}
    |          ^^^^^^^^^^^^^^^^^^^^
 
-error: expected identifier, found `123`
-  --> $DIR/syntax-errors.rs:34:29
+error: expected identifier or string literal
+  --> $DIR/syntax-errors.rs:88:26
    |
-LL |         ${concat($ex, aaaa, 123)}
-   |                             ^^^ help: try removing `123`
+LL |         let ${concat(_a, 'b')}: () = ();
+   |                          ^^^
+
+error: expected identifier or string literal
+  --> $DIR/syntax-errors.rs:91:26
+   |
+LL |         let ${concat(_a, 1)}: () = ();
+   |                          ^
+
+error: expected identifier or string literal
+  --> $DIR/syntax-errors.rs:94:30
+   |
+LL |         let ${concat($ident, 'b')}: () = ();
+   |                              ^^^
+
+error: expected identifier or string literal
+  --> $DIR/syntax-errors.rs:96:30
+   |
+LL |         let ${concat($ident, 1)}: () = ();
+   |                              ^
 
 error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
-  --> $DIR/syntax-errors.rs:25:19
+  --> $DIR/syntax-errors.rs:22:19
    |
 LL |         ${concat($ex, aaaa)}
    |                   ^^
 
 error: variable `foo` is not recognized in meta-variable expression
-  --> $DIR/syntax-errors.rs:41:30
+  --> $DIR/syntax-errors.rs:35:30
    |
 LL |         const ${concat(FOO, $foo)}: i32 = 2;
    |                              ^^^
 
-error: aborting due to 11 previous errors
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:42:14
+   |
+LL |         let ${concat("1", $ident)}: () = ();
+   |              ^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     starting_number!(_abc);
+   |     ---------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `starting_number` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:55:14
+   |
+LL |         let ${concat("\u{00BD}", $ident)}: () = ();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     starting_invalid_unicode!(_abc);
+   |     ------------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `starting_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:74:14
+   |
+LL |         let ${concat($ident, "\u{00BD}")}: () = ();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     ending_invalid_unicode!(_abc);
+   |     ----------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `ending_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected pattern, found `$`
+  --> $DIR/syntax-errors.rs:88:13
+   |
+LL |         let ${concat(_a, 'b')}: () = ();
+   |             ^ expected pattern
+...
+LL |     unsupported_literals!(_abc);
+   |     --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `unsupported_literals` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `${concat(..)}` is not generating a valid identifier
+  --> $DIR/syntax-errors.rs:81:14
+   |
+LL |         let ${concat("", "")}: () = ();
+   |              ^^^^^^^^^^^^^^^^
+...
+LL |     empty!();
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 18 previous errors
 
diff --git a/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs b/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs
new file mode 100644
index 00000000000..b2cfb211e2d
--- /dev/null
+++ b/tests/ui/macros/macro-metavar-expr-concat/unicode-expansion.rs
@@ -0,0 +1,14 @@
+//@ run-pass
+
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! turn_to_page {
+    ($ident:ident) => {
+        const ${concat("Ḧ", $ident)}: i32 = 394;
+    };
+}
+
+fn main() {
+    turn_to_page!(P);
+    assert_eq!(ḦP, 394);
+}
diff --git a/tests/ui/macros/out-of-scope-calls-false-positives.rs b/tests/ui/macros/out-of-scope-calls-false-positives.rs
new file mode 100644
index 00000000000..8d696c177e4
--- /dev/null
+++ b/tests/ui/macros/out-of-scope-calls-false-positives.rs
@@ -0,0 +1,10 @@
+//@ check-pass
+//@ needs-asm-support
+
+macro_rules! mac { () => { "" } }
+macro_rules! mac2 { () => { "auxiliary/issue-40469.rs" } }
+
+std::arch::global_asm!(mac!()); // OK
+include!(mac2!()); // OK
+
+fn main() {}
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index 8e4ba192d79..2c44ad2e0a4 100644
--- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -190,7 +190,7 @@ error: unrecognized meta-variable expression
 LL |     ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } };
    |                                 ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len
 
-error: expected identifier
+error: expected identifier or string literal
   --> $DIR/syntax-errors.rs:118:33
    |
 LL |     ( $( $i:ident ),* ) => { ${ {} } };
diff --git a/tests/ui/method-output-diff-issue-127263.rs b/tests/ui/method-output-diff-issue-127263.rs
new file mode 100644
index 00000000000..85a903e2453
--- /dev/null
+++ b/tests/ui/method-output-diff-issue-127263.rs
@@ -0,0 +1,8 @@
+fn bar() {}
+fn foo(x: i32) -> u32 {
+    0
+}
+fn main() {
+    let b: fn() -> u32 = bar; //~ ERROR mismatched types [E0308]
+    let f: fn(i32) = foo; //~ ERROR mismatched types [E0308]
+}
diff --git a/tests/ui/method-output-diff-issue-127263.stderr b/tests/ui/method-output-diff-issue-127263.stderr
new file mode 100644
index 00000000000..35b86114f16
--- /dev/null
+++ b/tests/ui/method-output-diff-issue-127263.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/method-output-diff-issue-127263.rs:6:26
+   |
+LL |     let b: fn() -> u32 = bar;
+   |            -----------   ^^^ expected fn pointer, found fn item
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `fn() -> u32`
+                 found fn item `fn() -> () {bar}`
+
+error[E0308]: mismatched types
+  --> $DIR/method-output-diff-issue-127263.rs:7:22
+   |
+LL |     let f: fn(i32) = foo;
+   |            -------   ^^^ expected fn pointer, found fn item
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `fn(_) -> ()`
+                 found fn item `fn(_) -> u32 {foo}`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
index fbd92f8f662..a75039b8237 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
@@ -1,5 +1,5 @@
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:8:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18
    |
 LL |         unsafe { mem::zeroed() }
    |                  ^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL |         unsafe { mem::zeroed() }
    = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:23:13
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13
    |
 LL |             core::mem::transmute(Zst)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL |             core::mem::transmute(Zst)
    = help: specify the type explicitly
 
 warning: never type fallback affects this union access
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:39:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18
    |
 LL |         unsafe { Union { a: () }.b }
    |                  ^^^^^^^^^^^^^^^^^
@@ -30,7 +30,7 @@ LL |         unsafe { Union { a: () }.b }
    = help: specify the type explicitly
 
 warning: never type fallback affects this raw pointer dereference
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:49:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18
    |
 LL |         unsafe { *ptr::from_ref(&()).cast() }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +40,7 @@ LL |         unsafe { *ptr::from_ref(&()).cast() }
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:67:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18
    |
 LL |         unsafe { internally_create(x) }
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@ LL |         unsafe { internally_create(x) }
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:83:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18
    |
 LL |         unsafe { zeroed() }
    |                  ^^^^^^^^
@@ -60,7 +60,7 @@ LL |         unsafe { zeroed() }
    = help: specify the type explicitly
 
 warning: never type fallback affects this `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:22
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22
    |
 LL |         let zeroed = mem::zeroed;
    |                      ^^^^^^^^^^^
@@ -70,7 +70,7 @@ LL |         let zeroed = mem::zeroed;
    = help: specify the type explicitly
 
 warning: never type fallback affects this `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:98:17
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17
    |
 LL |         let f = internally_create;
    |                 ^^^^^^^^^^^^^^^^^
@@ -80,7 +80,7 @@ LL |         let f = internally_create;
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` method
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:122:13
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13
    |
 LL |             S(marker::PhantomData).create_out_of_thin_air()
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |             S(marker::PhantomData).create_out_of_thin_air()
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:19
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19
    |
 LL |             match send_message::<_ /* ?0 */>() {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
new file mode 100644
index 00000000000..4138e9f8c86
--- /dev/null
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
@@ -0,0 +1,116 @@
+error: never type fallback affects this call to an `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18
+   |
+LL |         unsafe { mem::zeroed() }
+   |                  ^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+   = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default
+
+error: never type fallback affects this call to an `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:30:13
+   |
+LL |             core::mem::transmute(Zst)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this union access
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:47:18
+   |
+LL |         unsafe { Union { a: () }.b }
+   |                  ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this raw pointer dereference
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:58:18
+   |
+LL |         unsafe { *ptr::from_ref(&()).cast() }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this call to an `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:18
+   |
+LL |         unsafe { internally_create(x) }
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this call to an `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:97:18
+   |
+LL |         unsafe { zeroed() }
+   |                  ^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:92:22
+   |
+LL |         let zeroed = mem::zeroed;
+   |                      ^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:115:17
+   |
+LL |         let f = internally_create;
+   |                 ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this call to an `unsafe` method
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:140:13
+   |
+LL |             S(marker::PhantomData).create_out_of_thin_air()
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+
+error: never type fallback affects this call to an `unsafe` function
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:158:19
+   |
+LL |             match send_message::<_ /* ?0 */>() {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |         msg_send!();
+   |         ----------- in this macro invocation
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
+   = help: specify the type explicitly
+   = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: the type `!` does not permit zero-initialization
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:13:18
+   |
+LL |         unsafe { mem::zeroed() }
+   |                  ^^^^^^^^^^^^^ this code causes undefined behavior when executed
+   |
+   = note: the `!` type has no valid value
+   = note: `#[warn(invalid_value)]` on by default
+
+error: aborting due to 10 previous errors; 1 warning emitted
+
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
index d65bfee843e..c96f4dda3f8 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
@@ -1,4 +1,9 @@
-//@ check-pass
+//@ revisions: e2015 e2024
+//@[e2015] check-pass
+//@[e2024] check-fail
+//@[e2024] edition:2024
+//@[e2024] compile-flags: -Zunstable-options
+
 use std::{marker, mem, ptr};
 
 fn main() {}
@@ -6,8 +11,10 @@ fn main() {}
 fn _zero() {
     if false {
         unsafe { mem::zeroed() }
-        //~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function
         //~| warn: this will change its meaning in a future release!
+        //[e2024]~| warning: the type `!` does not permit zero-initialization
     } else {
         return;
     };
@@ -21,7 +28,8 @@ fn _trans() {
         unsafe {
             struct Zst;
             core::mem::transmute(Zst)
-            //~^ warn: never type fallback affects this call to an `unsafe` function
+            //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function
+            //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function
             //~| warn: this will change its meaning in a future release!
         }
     } else {
@@ -37,7 +45,8 @@ fn _union() {
         }
 
         unsafe { Union { a: () }.b }
-        //~^ warn: never type fallback affects this union access
+        //[e2015]~^ warn: never type fallback affects this union access
+        //[e2024]~^^ error: never type fallback affects this union access
         //~| warn: this will change its meaning in a future release!
     } else {
         return;
@@ -47,7 +56,8 @@ fn _union() {
 fn _deref() {
     if false {
         unsafe { *ptr::from_ref(&()).cast() }
-        //~^ warn: never type fallback affects this raw pointer dereference
+        //[e2015]~^ warn: never type fallback affects this raw pointer dereference
+        //[e2024]~^^ error: never type fallback affects this raw pointer dereference
         //~| warn: this will change its meaning in a future release!
     } else {
         return;
@@ -57,7 +67,9 @@ fn _deref() {
 fn _only_generics() {
     if false {
         unsafe fn internally_create<T>(_: Option<T>) {
-            let _ = mem::zeroed::<T>();
+            unsafe {
+                let _ = mem::zeroed::<T>();
+            }
         }
 
         // We need the option (and unwrap later) to call a function in a way,
@@ -65,7 +77,8 @@ fn _only_generics() {
         let x = None;
 
         unsafe { internally_create(x) }
-        //~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function
         //~| warn: this will change its meaning in a future release!
 
         x.unwrap()
@@ -77,11 +90,13 @@ fn _only_generics() {
 fn _stored_function() {
     if false {
         let zeroed = mem::zeroed;
-        //~^ warn: never type fallback affects this `unsafe` function
+        //[e2015]~^ warn: never type fallback affects this `unsafe` function
+        //[e2024]~^^ error: never type fallback affects this `unsafe` function
         //~| warn: this will change its meaning in a future release!
 
         unsafe { zeroed() }
-        //~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function
+        //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function
         //~| warn: this will change its meaning in a future release!
     } else {
         return;
@@ -91,12 +106,15 @@ fn _stored_function() {
 fn _only_generics_stored_function() {
     if false {
         unsafe fn internally_create<T>(_: Option<T>) {
-            let _ = mem::zeroed::<T>();
+            unsafe {
+                let _ = mem::zeroed::<T>();
+            }
         }
 
         let x = None;
         let f = internally_create;
-        //~^ warn: never type fallback affects this `unsafe` function
+        //[e2015]~^ warn: never type fallback affects this `unsafe` function
+        //[e2024]~^^ error: never type fallback affects this `unsafe` function
         //~| warn: this will change its meaning in a future release!
 
         unsafe { f(x) }
@@ -120,7 +138,8 @@ fn _method() {
     if false {
         unsafe {
             S(marker::PhantomData).create_out_of_thin_air()
-            //~^ warn: never type fallback affects this call to an `unsafe` method
+            //[e2015]~^ warn: never type fallback affects this call to an `unsafe` method
+            //[e2024]~^^ error: never type fallback affects this call to an `unsafe` method
             //~| warn: this will change its meaning in a future release!
         }
     } else {
@@ -137,7 +156,8 @@ fn _objc() {
     macro_rules! msg_send {
         () => {
             match send_message::<_ /* ?0 */>() {
-                //~^ warn: never type fallback affects this call to an `unsafe` function
+                //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function
+                //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function
                 //~| warn: this will change its meaning in a future release!
                 Ok(x) => x,
                 Err(_) => loop {},
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
index 812f7a0692f..4fea52fec6e 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
@@ -5,7 +5,7 @@ LL | fn panic(info: PanicInfo) -> () {}
    |                ^^^^^^^^^ expected `&PanicInfo<'_>`, found `PanicInfo<'_>`
    |
    = note: expected signature `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !`
-              found signature `for<'a> fn(PanicInfo<'a>)`
+              found signature `for<'a> fn(PanicInfo<'a>) -> ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr
deleted file mode 100644
index 03536dca1e8..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.nn.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output`
-  --> $DIR/issue-100222.rs:34:12
-   |
-LL |     fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
-   |            ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
-   |
-   = note:      expected unit type `()`
-           found mutable reference `&mut <() as Index>::Output`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr
deleted file mode 100644
index 6a70a503606..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.ny.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output`
-  --> $DIR/issue-100222.rs:25:12
-   |
-LL |     fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
-   |            ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
-   |
-   = note:      expected unit type `()`
-           found mutable reference `&mut <() as Index>::Output`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
index 7949772a2b4..47f9fc664ce 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.rs
@@ -1,6 +1,7 @@
 //@ revisions: nn ny yn yy
-//@ known-bug: #110395
 //@ compile-flags: -Znext-solver
+//@ check-pass
+
 #![allow(incomplete_features)]
 #![feature(const_trait_impl, effects, associated_type_defaults, const_mut_refs)]
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr
deleted file mode 100644
index 03536dca1e8..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yn.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output`
-  --> $DIR/issue-100222.rs:34:12
-   |
-LL |     fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
-   |            ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
-   |
-   = note:      expected unit type `()`
-           found mutable reference `&mut <() as Index>::Output`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr
deleted file mode 100644
index 6a70a503606..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/issue-100222.yy.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0271]: type mismatch resolving `<() as Index>::Output == &mut <() as Index>::Output`
-  --> $DIR/issue-100222.rs:25:12
-   |
-LL |     fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
-   |            ^^^^^^^^^ expected `()`, found `&mut <() as Index>::Output`
-   |
-   = note:      expected unit type `()`
-           found mutable reference `&mut <() as Index>::Output`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr
index 77d542c729a..db457b77a23 100644
--- a/tests/ui/traits/impl-method-mismatch.stderr
+++ b/tests/ui/traits/impl-method-mismatch.stderr
@@ -10,7 +10,7 @@ note: type in trait
 LL |     fn jumbo(&self, x: &usize) -> usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected signature `fn(&_, &_) -> usize`
-              found signature `unsafe fn(&_, &_)`
+              found signature `unsafe fn(&_, &_) -> ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
index e0b23bd8110..c2029a5a1c8 100644
--- a/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
+++ b/tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr
@@ -17,10 +17,6 @@ note: required by a bound in `is_send`
    |
 LL |     fn is_send(_: impl Send) {}
    |                        ^^^^ required by this bound in `is_send`
-help: consider dereferencing here
-   |
-LL |     is_send(*foo());
-   |             +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs b/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs
new file mode 100644
index 00000000000..f8c8a17b7e5
--- /dev/null
+++ b/tests/ui/traits/next-solver/typeck/receiver-self-ty-check-eq.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Fixes a regression in `receiver_is_valid` in wfcheck where we were using
+// `InferCtxt::can_eq` instead of processing alias-relate goals, leading to false
+// positives, not deref'ing enough steps to check the receiver is valid.
+
+trait Mirror {
+    type Mirror: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+    type Mirror = T;
+}
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+impl Foo for <() as Mirror>::Mirror {
+    fn foo(&self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
index e992d059daf..09efd7a9e7e 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr
@@ -8,7 +8,7 @@ LL |     fn bar(self: Bar<u32>) {
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0307]: invalid `self` parameter type: `&Bar<u32>`
-  --> $DIR/method_resolution3.rs:21:18
+  --> $DIR/method_resolution3.rs:20:18
    |
 LL |     fn baz(self: &Bar<u32>) {
    |                  ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
index 9272017cdf5..09efd7a9e7e 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr
@@ -1,15 +1,21 @@
-error[E0271]: type mismatch resolving `Foo == u32`
+error[E0307]: invalid `self` parameter type: `Bar<u32>`
   --> $DIR/method_resolution3.rs:16:18
    |
 LL |     fn bar(self: Bar<u32>) {
-   |                  ^^^^^^^^ types differ
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0271]: type mismatch resolving `Foo == u32`
-  --> $DIR/method_resolution3.rs:21:18
+error[E0307]: invalid `self` parameter type: `&Bar<u32>`
+  --> $DIR/method_resolution3.rs:20:18
    |
 LL |     fn baz(self: &Bar<u32>) {
-   |                  ^^^^^^^^^ types differ
+   |                  ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs
index 447f3144b82..0e6176bfe03 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs
@@ -14,13 +14,11 @@ struct Bar<T>(T);
 
 impl Bar<Foo> {
     fn bar(self: Bar<u32>) {
-        //[current]~^ ERROR: invalid `self` parameter
-        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        //~^ ERROR: invalid `self` parameter
         self.foo()
     }
     fn baz(self: &Bar<u32>) {
-        //[current]~^ ERROR: invalid `self` parameter
-        //[next]~^^ ERROR: type mismatch resolving `Foo == u32`
+        //~^ ERROR: invalid `self` parameter
         self.foo()
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
index 3a2ca18f890..8ffdb21f251 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -8,7 +8,7 @@ LL |     fn foo(self: Bar<Foo>) {
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
-  --> $DIR/method_resolution4.rs:32:20
+  --> $DIR/method_resolution4.rs:31:20
    |
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
index 33ed2800ebe..8ffdb21f251 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -1,15 +1,21 @@
-error[E0271]: type mismatch resolving `u32 == Foo`
+error[E0307]: invalid `self` parameter type: `Bar<Foo>`
   --> $DIR/method_resolution4.rs:27:18
    |
 LL |     fn foo(self: Bar<Foo>) {
-   |                  ^^^^^^^^ types differ
+   |                  ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error[E0271]: type mismatch resolving `u32 == Foo`
-  --> $DIR/method_resolution4.rs:32:20
+error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
+  --> $DIR/method_resolution4.rs:31:20
    |
 LL |     fn foomp(self: &Bar<Foo>) {
-   |                    ^^^^^^^^^ types differ
+   |                    ^^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or a type that dereferences to it
+   = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs
index 42ed04b3c30..f33b4e473ae 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs
@@ -25,13 +25,11 @@ impl Bar<Foo> {
 
 impl Bar<u32> {
     fn foo(self: Bar<Foo>) {
-        //[current]~^ ERROR: invalid `self` parameter
-        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        //~^ ERROR: invalid `self` parameter
         self.bar()
     }
     fn foomp(self: &Bar<Foo>) {
-        //[current]~^ ERROR: invalid `self` parameter
-        //[next]~^^ ERROR: type mismatch resolving `u32 == Foo`
+        //~^ ERROR: invalid `self` parameter
         self.bar()
     }
 }
diff --git a/tests/ui/typeck/ice-with-expr-not-struct-127332.rs b/tests/ui/typeck/ice-with-expr-not-struct-127332.rs
new file mode 100644
index 00000000000..f3ea360e7e9
--- /dev/null
+++ b/tests/ui/typeck/ice-with-expr-not-struct-127332.rs
@@ -0,0 +1,15 @@
+// Regression test for ICE #127332
+
+// Tests that we do not ICE when a with expr is
+// not a struct but something else like an enum
+
+fn main() {
+    let x = || {
+        enum Foo {
+            A { x: u32 },
+        }
+        let orig = Foo::A { x: 5 };
+        Foo::A { x: 6, ..orig };
+        //~^ ERROR functional record update syntax requires a struct
+    };
+}
diff --git a/tests/ui/typeck/ice-with-expr-not-struct-127332.stderr b/tests/ui/typeck/ice-with-expr-not-struct-127332.stderr
new file mode 100644
index 00000000000..446f49e8639
--- /dev/null
+++ b/tests/ui/typeck/ice-with-expr-not-struct-127332.stderr
@@ -0,0 +1,9 @@
+error[E0436]: functional record update syntax requires a struct
+  --> $DIR/ice-with-expr-not-struct-127332.rs:12:26
+   |
+LL |         Foo::A { x: 6, ..orig };
+   |                          ^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0436`.
diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr
index b615d9fb45c..2912977a461 100644
--- a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr
+++ b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr
@@ -2,10 +2,8 @@ error[E0308]: mismatched types
   --> $DIR/ptr-null-mutability-suggestions.rs:9:24
    |
 LL |     expecting_null_mut(ptr::null());
-   |     ------------------ ^^^^^^^^^^^
-   |     |                  |
-   |     |                  types differ in mutability
-   |     |                  help: consider using `core::ptr::null_mut` instead: `core::ptr::null_mut()`
+   |     ------------------ ^^^^^^^^^^^ types differ in mutability
+   |     |
    |     arguments to this function are incorrect
    |
    = note: expected raw pointer `*mut u8`
@@ -15,6 +13,10 @@ note: function defined here
    |
 LL | fn expecting_null_mut(_: *mut u8) {}
    |    ^^^^^^^^^^^^^^^^^^ ----------
+help: consider using `core::ptr::null_mut` instead
+   |
+LL |     expecting_null_mut(core::ptr::null_mut());
+   |                        ~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error