about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock72
-rw-r--r--compiler/rustc_codegen_llvm/src/va_arg.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs18
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs137
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/effect_goals.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs80
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs8
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs7
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs3
-rw-r--r--compiler/rustc_type_ir/src/interner.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/net/connection/socket/hermit.rs3
-rw-r--r--library/std/src/sys/pal/hermit/os.rs2
-rw-r--r--library/std/src/sys/pal/unix/weak.rs130
-rw-r--r--library/std/src/sys/pal/unix/weak/tests.rs32
-rw-r--r--library/std/src/sys/sync/once/queue.rs4
-rw-r--r--library/std/src/thread/mod.rs67
-rw-r--r--library/std/src/thread/tests.rs4
-rw-r--r--library/std/tests/sync/condvar.rs18
-rw-r--r--library/std/tests/sync/lib.rs3
-rw-r--r--library/std/tests/sync/mutex.rs4
-rw-r--r--library/std/tests/sync/rwlock.rs8
-rw-r--r--library/std_detect/src/detect/os/linux/aarch64.rs77
-rw-r--r--package-lock.json8
-rw-r--r--package.json2
-rw-r--r--src/bootstrap/defaults/bootstrap.dist.toml4
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs14
-rw-r--r--src/bootstrap/src/core/config/mod.rs2
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/librustdoc/html/static/js/search.js6
-rw-r--r--src/librustdoc/passes/lint/bare_urls.rs57
-rw-r--r--src/tools/miri/README.md1
-rw-r--r--src/tools/tidy/src/extra_checks/mod.rs52
-rw-r--r--src/tools/tidy/src/extra_checks/rustdoc_js.rs6
-rw-r--r--tests/assembly-llvm/c-variadic-arm.rs26
-rw-r--r--tests/codegen-llvm/c-variadic-lifetime.rs21
-rw-r--r--tests/rustdoc-js/literal-path.js23
-rw-r--r--tests/rustdoc-js/literal-path.rs7
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.fixed14
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.rs14
-rw-r--r--tests/rustdoc-ui/lints/bare-urls.stderr70
-rw-r--r--tests/ui/feature-gates/feature-gate-sanitize.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-sanitize.stderr4
-rw-r--r--tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.next.stderr16
-rw-r--r--tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.rs31
-rw-r--r--tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.rs25
-rw-r--r--tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.stderr25
-rw-r--r--tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket.rs25
-rw-r--r--tests/ui/impl-trait/non-defining-uses/multiple-opaques-ambig.rs23
-rw-r--r--tests/ui/impl-trait/non-defining-uses/multiple-opaques-ok.rs37
-rw-r--r--tests/ui/impl-trait/non-defining-uses/no-rigid-alias.rs27
-rw-r--r--tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs19
-rw-r--r--tests/ui/impl-trait/non-defining-uses/use-item-bound-over-blanket-impl.rs30
-rw-r--r--tests/ui/impl-trait/non-defining-uses/use-item-bound.rs25
-rw-r--r--tests/ui/macros/metavar-expressions/concat-allowed-operations.rs18
-rw-r--r--tests/ui/macros/metavar-expressions/concat-usage-errors.rs10
-rw-r--r--tests/ui/macros/metavar-expressions/concat-usage-errors.stderr40
60 files changed, 1104 insertions, 293 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8be13e84596..2dc6e8ff103 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2347,11 +2347,11 @@ dependencies = [
 
 [[package]]
 name = "miow"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044"
+checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08"
 dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -6316,15 +6316,6 @@ dependencies = [
 
 [[package]]
 name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
@@ -6352,21 +6343,6 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
-[[package]]
-name = "windows-targets"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
@@ -6409,12 +6385,6 @@ dependencies = [
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
@@ -6427,12 +6397,6 @@ checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
@@ -6445,12 +6409,6 @@ checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
@@ -6475,12 +6433,6 @@ checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
@@ -6493,12 +6445,6 @@ checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
@@ -6511,12 +6457,6 @@ checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
@@ -6529,12 +6469,6 @@ checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 7eb5d302058..ab08125217f 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -908,6 +908,21 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
             )
         }
         "aarch64" => emit_aapcs_va_arg(bx, addr, target_ty),
+        "arm" => {
+            // Types wider than 16 bytes are not currently supported. Clang has special logic for
+            // such types, but `VaArgSafe` is not implemented for any type that is this large.
+            assert!(bx.cx.size_of(target_ty).bytes() <= 16);
+
+            emit_ptr_va_arg(
+                bx,
+                addr,
+                target_ty,
+                PassMode::Direct,
+                SlotSize::Bytes4,
+                AllowHigherAlign::Yes,
+                ForceRightAdjust::No,
+            )
+        }
         "s390x" => emit_s390x_va_arg(bx, addr, target_ty),
         "powerpc" => emit_powerpc_va_arg(bx, addr, target_ty),
         "powerpc64" | "powerpc64le" => emit_ptr_va_arg(
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 5f6976f5d00..6492ef73956 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -520,7 +520,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 LocalRef::Place(va_list) => {
                     bx.va_end(va_list.val.llval);
 
-                    // Explicitly end the lifetime of the `va_list`, this matters for LLVM.
+                    // Explicitly end the lifetime of the `va_list`, improves LLVM codegen.
                     bx.lifetime_end(va_list.val.llval, va_list.layout.size);
                 }
                 _ => bug!("C-variadic function must have a `VaList` place"),
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 06873313e2e..6b109e8b8e2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -438,6 +438,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
             if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() {
                 let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
+
+                // Explicitly start the lifetime of the `va_list`, improves LLVM codegen.
+                bx.lifetime_start(va_list.val.llval, va_list.layout.size);
+
                 bx.va_start(va_list.val.llval);
 
                 return LocalRef::Place(va_list);
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index e4e4866b64c..ed8aa71d59d 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -940,11 +940,27 @@ fn extract_symbol_from_pnr<'a>(
         {
             Ok(*symbol)
         }
+        ParseNtResult::Literal(expr)
+            if let ExprKind::Lit(lit @ Lit { kind: LitKind::Integer, symbol, suffix }) =
+                &expr.kind =>
+        {
+            if lit.is_semantic_float() {
+                Err(dcx
+                    .struct_err("floats are not supported as metavariables of `${concat(..)}`")
+                    .with_span(span_err))
+            } else if suffix.is_none() {
+                Ok(*symbol)
+            } else {
+                Err(dcx
+                    .struct_err("integer metavariables of `${concat(..)}` must not be suffixed")
+                    .with_span(span_err))
+            }
+        }
         _ => Err(dcx
             .struct_err(
                 "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`",
             )
-            .with_note("currently only string literals are supported")
+            .with_note("currently only string and integer literals are supported")
             .with_span(span_err)),
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 218ac2cfbc1..8ea767dccd3 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -651,7 +651,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
             | ty::Bound(_, _) => bug!("unexpected self type: {self_ty}"),
         }
 
-        let trait_impls = tcx.trait_impls_of(trait_def_id);
+        #[allow(rustc::usage_of_type_ir_traits)]
+        self.for_each_blanket_impl(trait_def_id, f)
+    }
+    fn for_each_blanket_impl(self, trait_def_id: DefId, mut f: impl FnMut(DefId)) {
+        let trait_impls = self.trait_impls_of(trait_def_id);
         for &impl_def_id in trait_impls.blanket_impls() {
             f(impl_def_id);
         }
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index e3cf0330b14..fb777496e31 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -11,8 +11,9 @@ use rustc_type_ir::lang_items::SolverTraitLangItem;
 use rustc_type_ir::search_graph::CandidateHeadUsages;
 use rustc_type_ir::solve::SizedTraitKind;
 use rustc_type_ir::{
-    self as ty, Interner, TypeFlags, TypeFoldable, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt as _, TypeVisitor, TypingMode, Upcast as _, elaborate,
+    self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
+    elaborate,
 };
 use tracing::{debug, instrument};
 
@@ -187,6 +188,7 @@ where
         ecx: &mut EvalCtxt<'_, D>,
         goal: Goal<I, Self>,
         impl_def_id: I::ImplId,
+        then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
     ) -> Result<Candidate<I>, NoSolution>;
 
     /// If the predicate contained an error, we want to avoid emitting unnecessary trait
@@ -365,6 +367,15 @@ pub(super) enum AssembleCandidatesFrom {
     EnvAndBounds,
 }
 
+impl AssembleCandidatesFrom {
+    fn should_assemble_impl_candidates(&self) -> bool {
+        match self {
+            AssembleCandidatesFrom::All => true,
+            AssembleCandidatesFrom::EnvAndBounds => false,
+        }
+    }
+}
+
 /// This is currently used to track the [CandidateHeadUsages] of all failed `ParamEnv`
 /// candidates. This is then used to ignore their head usages in case there's another
 /// always applicable `ParamEnv` candidate. Look at how `param_env_head_usages` is
@@ -397,14 +408,15 @@ where
             return (candidates, failed_candidate_info);
         };
 
+        let goal: Goal<I, G> = goal
+            .with(self.cx(), goal.predicate.with_replaced_self_ty(self.cx(), normalized_self_ty));
+
         if normalized_self_ty.is_ty_var() {
             debug!("self type has been normalized to infer");
-            candidates.extend(self.forced_ambiguity(MaybeCause::Ambiguity));
+            self.try_assemble_bounds_via_registered_opaques(goal, assemble_from, &mut candidates);
             return (candidates, failed_candidate_info);
         }
 
-        let goal: Goal<I, G> = goal
-            .with(self.cx(), goal.predicate.with_replaced_self_ty(self.cx(), normalized_self_ty));
         // Vars that show up in the rest of the goal substs may have been constrained by
         // normalizing the self type as well, since type variables are not uniquified.
         let goal = self.resolve_vars_if_possible(goal);
@@ -484,8 +496,9 @@ where
                 if cx.impl_is_default(impl_def_id) {
                     return;
                 }
-
-                match G::consider_impl_candidate(self, goal, impl_def_id) {
+                match G::consider_impl_candidate(self, goal, impl_def_id, |ecx, certainty| {
+                    ecx.evaluate_added_goals_and_make_canonical_response(certainty)
+                }) {
                     Ok(candidate) => candidates.push(candidate),
                     Err(NoSolution) => (),
                 }
@@ -943,6 +956,116 @@ where
         }
     }
 
+    /// If the self type is the hidden type of an opaque, try to assemble
+    /// candidates for it by consider its item bounds and by using blanket
+    /// impls. This is used to incompletely guide type inference when handling
+    /// non-defining uses in the defining scope.
+    ///
+    /// We otherwise just fail fail with ambiguity. Even if we're using an
+    /// opaque type item bound or a blank impls, we still force its certainty
+    /// to be `Maybe` so that we properly prove this goal later.
+    ///
+    /// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/182>
+    /// for why this is necessary.
+    fn try_assemble_bounds_via_registered_opaques<G: GoalKind<D>>(
+        &mut self,
+        goal: Goal<I, G>,
+        assemble_from: AssembleCandidatesFrom,
+        candidates: &mut Vec<Candidate<I>>,
+    ) {
+        let self_ty = goal.predicate.self_ty();
+        // If the self type is sub unified with any opaque type, we
+        // also look at blanket impls for it.
+        let mut assemble_blanket_impls = false;
+        for alias_ty in self.opaques_with_sub_unified_hidden_type(self_ty) {
+            assemble_blanket_impls = true;
+            debug!("self ty is sub unified with {alias_ty:?}");
+
+            struct ReplaceOpaque<I: Interner> {
+                cx: I,
+                alias_ty: ty::AliasTy<I>,
+                self_ty: I::Ty,
+            }
+            impl<I: Interner> TypeFolder<I> for ReplaceOpaque<I> {
+                fn cx(&self) -> I {
+                    self.cx
+                }
+                fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
+                    if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() {
+                        if alias_ty == self.alias_ty {
+                            return self.self_ty;
+                        }
+                    }
+                    ty.super_fold_with(self)
+                }
+            }
+
+            // We look at all item-bounds of the opaque, replacing the
+            // opaque with the current self type before considering
+            // them as a candidate. Imagine e've got `?x: Trait<?y>`
+            // and `?x` has been sub-unified with the hidden type of
+            // `impl Trait<u32>`, We take the item bound `opaque: Trait<u32>`
+            // and replace all occurrences of `opaque` with `?x`. This results
+            // in a `?x: Trait<u32>` alias-bound candidate.
+            for item_bound in self
+                .cx()
+                .item_self_bounds(alias_ty.def_id)
+                .iter_instantiated(self.cx(), alias_ty.args)
+            {
+                let assumption =
+                    item_bound.fold_with(&mut ReplaceOpaque { cx: self.cx(), alias_ty, self_ty });
+                candidates.extend(G::probe_and_match_goal_against_assumption(
+                    self,
+                    CandidateSource::AliasBound,
+                    goal,
+                    assumption,
+                    |ecx| {
+                        // We want to reprove this goal once we've inferred the
+                        // hidden type, so we force the certainty to `Maybe`.
+                        ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
+                    },
+                ));
+            }
+        }
+
+        // We also need to consider blanket impls for not-yet-defined opaque types.
+        //
+        // See tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs for an example.
+        if assemble_blanket_impls && assemble_from.should_assemble_impl_candidates() {
+            let cx = self.cx();
+            cx.for_each_blanket_impl(goal.predicate.trait_def_id(cx), |impl_def_id| {
+                // For every `default impl`, there's always a non-default `impl`
+                // that will *also* apply. There's no reason to register a candidate
+                // for this impl, since it is *not* proof that the trait goal holds.
+                if cx.impl_is_default(impl_def_id) {
+                    return;
+                }
+
+                match G::consider_impl_candidate(self, goal, impl_def_id, |ecx, certainty| {
+                    if ecx.shallow_resolve(self_ty).is_ty_var() {
+                        // We force the certainty of impl candidates to be `Maybe`.
+                        let certainty = certainty.and(Certainty::AMBIGUOUS);
+                        ecx.evaluate_added_goals_and_make_canonical_response(certainty)
+                    } else {
+                        // We don't want to use impls if they constrain the opaque.
+                        //
+                        // FIXME(trait-system-refactor-initiative#229): This isn't
+                        // perfect yet as it still allows us to incorrectly constrain
+                        // other inference variables.
+                        Err(NoSolution)
+                    }
+                }) {
+                    Ok(candidate) => candidates.push(candidate),
+                    Err(NoSolution) => (),
+                }
+            });
+        }
+
+        if candidates.is_empty() {
+            candidates.extend(self.forced_ambiguity(MaybeCause::Ambiguity));
+        }
+    }
+
     /// Assemble and merge candidates for goals which are related to an underlying trait
     /// goal. Right now, this is normalizes-to and host effect goals.
     ///
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index 6646857a136..cb72c1cd92b 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -124,6 +124,7 @@ where
         ecx: &mut EvalCtxt<'_, D>,
         goal: Goal<I, Self>,
         impl_def_id: I::ImplId,
+        then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
     ) -> Result<Candidate<I>, NoSolution> {
         let cx = ecx.cx();
 
@@ -175,7 +176,7 @@ where
                 });
             ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
 
-            ecx.evaluate_added_goals_and_make_canonical_response(certainty)
+            then(ecx, certainty)
         })
     }
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 5cd597d4fe6..3e3a5246f3d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -407,20 +407,21 @@ where
         // If we have run this goal before, and it was stalled, check that any of the goal's
         // args have changed. Otherwise, we don't need to re-run the goal because it'll remain
         // stalled, since it'll canonicalize the same way and evaluation is pure.
-        if let Some(stalled_on) = stalled_on
-            && !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
-            && !self
-                .delegate
-                .opaque_types_storage_num_entries()
-                .needs_reevaluation(stalled_on.num_opaques)
+        if let Some(GoalStalledOn { num_opaques, ref stalled_vars, ref sub_roots, stalled_cause }) =
+            stalled_on
+            && !stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value))
+            && !sub_roots
+                .iter()
+                .any(|&vid| self.delegate.sub_unification_table_root_var(vid) != vid)
+            && !self.delegate.opaque_types_storage_num_entries().needs_reevaluation(num_opaques)
         {
             return Ok((
                 NestedNormalizationGoals::empty(),
                 GoalEvaluation {
                     goal,
-                    certainty: Certainty::Maybe(stalled_on.stalled_cause),
+                    certainty: Certainty::Maybe(stalled_cause),
                     has_changed: HasChanged::No,
-                    stalled_on: Some(stalled_on),
+                    stalled_on,
                 },
             ));
         }
@@ -476,16 +477,6 @@ where
                 HasChanged::No => {
                     let mut stalled_vars = orig_values;
 
-                    // Remove the canonicalized universal vars, since we only care about stalled existentials.
-                    stalled_vars.retain(|arg| match arg.kind() {
-                        ty::GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Infer(_)),
-                        ty::GenericArgKind::Const(ct) => {
-                            matches!(ct.kind(), ty::ConstKind::Infer(_))
-                        }
-                        // Lifetimes can never stall goals.
-                        ty::GenericArgKind::Lifetime(_) => false,
-                    });
-
                     // Remove the unconstrained RHS arg, which is expected to have changed.
                     if let Some(normalizes_to) = goal.predicate.as_normalizes_to() {
                         let normalizes_to = normalizes_to.skip_binder();
@@ -497,6 +488,27 @@ where
                         stalled_vars.swap_remove(idx);
                     }
 
+                    // Remove the canonicalized universal vars, since we only care about stalled existentials.
+                    let mut sub_roots = Vec::new();
+                    stalled_vars.retain(|arg| match arg.kind() {
+                        // Lifetimes can never stall goals.
+                        ty::GenericArgKind::Lifetime(_) => false,
+                        ty::GenericArgKind::Type(ty) => match ty.kind() {
+                            ty::Infer(ty::TyVar(vid)) => {
+                                sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
+                                true
+                            }
+                            ty::Infer(_) => true,
+                            ty::Param(_) | ty::Placeholder(_) => false,
+                            _ => unreachable!("unexpected orig_value: {ty:?}"),
+                        },
+                        ty::GenericArgKind::Const(ct) => match ct.kind() {
+                            ty::ConstKind::Infer(_) => true,
+                            ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => false,
+                            _ => unreachable!("unexpected orig_value: {ct:?}"),
+                        },
+                    });
+
                     Some(GoalStalledOn {
                         num_opaques: canonical_goal
                             .canonical
@@ -505,6 +517,7 @@ where
                             .opaque_types
                             .len(),
                         stalled_vars,
+                        sub_roots,
                         stalled_cause,
                     })
                 }
@@ -1047,6 +1060,10 @@ where
         self.delegate.resolve_vars_if_possible(value)
     }
 
+    pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty {
+        self.delegate.shallow_resolve(ty)
+    }
+
     pub(super) fn eager_resolve_region(&self, r: I::Region) -> I::Region {
         if let ty::ReVar(vid) = r.kind() {
             self.delegate.opportunistic_resolve_lt_var(vid)
@@ -1163,6 +1180,33 @@ where
     ) -> bool {
         may_use_unstable_feature(&**self.delegate, param_env, symbol)
     }
+
+    pub(crate) fn opaques_with_sub_unified_hidden_type(
+        &self,
+        self_ty: I::Ty,
+    ) -> impl Iterator<Item = ty::AliasTy<I>> + use<'a, D, I> {
+        let delegate = self.delegate;
+        delegate
+            .clone_opaque_types_lookup_table()
+            .into_iter()
+            .chain(delegate.clone_duplicate_opaque_types())
+            .filter_map(move |(key, hidden_ty)| {
+                if let ty::Infer(ty::TyVar(self_vid)) = self_ty.kind() {
+                    if let ty::Infer(ty::TyVar(hidden_vid)) = hidden_ty.kind() {
+                        if delegate.sub_unification_table_root_var(self_vid)
+                            == delegate.sub_unification_table_root_var(hidden_vid)
+                        {
+                            return Some(ty::AliasTy::new_from_args(
+                                delegate.cx(),
+                                key.def_id.into(),
+                                key.args,
+                            ));
+                        }
+                    }
+                }
+                None
+            })
+    }
 }
 
 /// Eagerly replace aliases with inference variables, emitting `AliasRelate`
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index db3460c4ff6..cd27c9c26c1 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -24,7 +24,7 @@ mod trait_goals;
 use derive_where::derive_where;
 use rustc_type_ir::inherent::*;
 pub use rustc_type_ir::solve::*;
-use rustc_type_ir::{self as ty, Interner, TypingMode};
+use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode};
 use tracing::instrument;
 
 pub use self::eval_ctxt::{
@@ -418,11 +418,6 @@ pub struct GoalEvaluation<I: Interner> {
     pub has_changed: HasChanged,
     /// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed
     /// before rerunning it.
-    ///
-    /// We knowingly ignore the `sub_root` of our inference variables here. This means we
-    /// may not reevaluate a goal even though a change to the `sub_root` could cause a goal
-    /// to make progress. Tracking them adds additional complexity for an incredibly minor
-    /// type inference improvement. We could look into properly handling this in the future.
     pub stalled_on: Option<GoalStalledOn<I>>,
 }
 
@@ -431,6 +426,7 @@ pub struct GoalEvaluation<I: Interner> {
 pub struct GoalStalledOn<I: Interner> {
     pub num_opaques: usize,
     pub stalled_vars: Vec<I::GenericArg>,
+    pub sub_roots: Vec<TyVid>,
     /// The cause that will be returned on subsequent evaluations if this goal remains stalled.
     pub stalled_cause: MaybeCause,
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index 6e6be829f52..54b92ebac1d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -194,6 +194,7 @@ where
         ecx: &mut EvalCtxt<'_, D>,
         goal: Goal<I, NormalizesTo<I>>,
         impl_def_id: I::ImplId,
+        then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
     ) -> Result<Candidate<I>, NoSolution> {
         let cx = ecx.cx();
 
@@ -314,8 +315,7 @@ where
                         // nested goal for consistency.
                         ty::TypingMode::Coherence => {
                             ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous));
-                            return ecx
-                                .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                            return then(ecx, Certainty::Yes);
                         }
                         ty::TypingMode::Analysis { .. }
                         | ty::TypingMode::Borrowck { .. }
@@ -325,8 +325,7 @@ where
                                 goal,
                                 goal.predicate.alias,
                             );
-                            return ecx
-                                .evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                            return then(ecx, Certainty::Yes);
                         }
                     }
                 } else {
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 3e720a47f32..a69e867289c 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -55,6 +55,7 @@ where
         ecx: &mut EvalCtxt<'_, D>,
         goal: Goal<I, TraitPredicate<I>>,
         impl_def_id: I::ImplId,
+        then: impl FnOnce(&mut EvalCtxt<'_, D>, Certainty) -> QueryResult<I>,
     ) -> Result<Candidate<I>, NoSolution> {
         let cx = ecx.cx();
 
@@ -112,7 +113,7 @@ where
                     .map(|pred| goal.with(cx, pred)),
             );
 
-            ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)
+            then(ecx, maximal_certainty)
         })
     }
 
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 3a83b1739ff..cf58aec14a6 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -347,6 +347,7 @@ pub trait Interner:
         self_ty: Self::Ty,
         f: impl FnMut(Self::ImplId),
     );
+    fn for_each_blanket_impl(self, trait_def_id: Self::TraitId, f: impl FnMut(Self::ImplId));
 
     fn has_item_definition(self, def_id: Self::DefId) -> bool;
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 97db0d6ab75..5725816c600 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -350,6 +350,7 @@
 #![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(fmt_internals)]
+#![feature(fn_ptr_trait)]
 #![feature(generic_atomic)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
diff --git a/library/std/src/sys/net/connection/socket/hermit.rs b/library/std/src/sys/net/connection/socket/hermit.rs
index f49821657d9..5200eaa5786 100644
--- a/library/std/src/sys/net/connection/socket/hermit.rs
+++ b/library/std/src/sys/net/connection/socket/hermit.rs
@@ -304,7 +304,8 @@ impl Socket {
     }
 
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        unimplemented!()
+        let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?;
+        if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
     }
 
     // This is used by sys_common code to abstract over Windows and Unix.
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index 0fe713a503b..9681964ed9b 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -3,7 +3,7 @@ use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
 use crate::sys::unsupported;
-use crate::{fmt, io, str};
+use crate::{fmt, io};
 
 pub fn errno() -> i32 {
     unsafe { hermit_abi::get_errno() }
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index c8cf75b876c..a3b980a3f3d 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -22,11 +22,24 @@
 #![allow(dead_code, unused_macros)]
 #![forbid(unsafe_op_in_unsafe_fn)]
 
-use crate::ffi::CStr;
-use crate::marker::PhantomData;
-use crate::sync::atomic::{self, Atomic, AtomicPtr, Ordering};
+use crate::ffi::{CStr, c_char, c_void};
+use crate::marker::{FnPtr, PhantomData};
+use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
 use crate::{mem, ptr};
 
+// We currently only test `dlsym!`, but that doesn't work on all platforms, so
+// we gate the tests to only the platforms where it is actually used.
+//
+// FIXME(joboet): add more tests, reorganise the whole module and get rid of
+//                `#[allow(dead_code, unused_macros)]`.
+#[cfg(any(
+    target_vendor = "apple",
+    all(target_os = "linux", target_env = "gnu"),
+    target_os = "freebsd",
+))]
+#[cfg(test)]
+mod tests;
+
 // We can use true weak linkage on ELF targets.
 #[cfg(all(unix, not(target_vendor = "apple")))]
 pub(crate) macro weak {
@@ -64,7 +77,7 @@ impl<F: Copy> ExternWeak<F> {
 
 pub(crate) macro dlsym {
     (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => (
-         dlsym!(
+        dlsym!(
             #[link_name = stringify!($name)]
             fn $name($($param : $t),*) -> $ret;
         );
@@ -73,21 +86,39 @@ pub(crate) macro dlsym {
         #[link_name = $sym:expr]
         fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
     ) => (
-        static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> =
-            DlsymWeak::new(concat!($sym, '\0'));
+        static DLSYM: DlsymWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
+            let Ok(name) = CStr::from_bytes_with_nul(concat!($sym, '\0').as_bytes()) else {
+                panic!("symbol name may not contain NUL")
+            };
+
+            // SAFETY: Whoever calls the function pointer returned by `get()`
+            // is responsible for ensuring that the signature is correct. Just
+            // like with extern blocks, this is syntactically enforced by making
+            // the function pointer be unsafe.
+            unsafe { DlsymWeak::new(name) }
+        };
+
         let $name = &DLSYM;
     )
 }
+
 pub(crate) struct DlsymWeak<F> {
-    name: &'static str,
+    /// A pointer to the nul-terminated name of the symbol.
+    // Use a pointer instead of `&'static CStr` to save space.
+    name: *const c_char,
     func: Atomic<*mut libc::c_void>,
     _marker: PhantomData<F>,
 }
 
-impl<F> DlsymWeak<F> {
-    pub(crate) const fn new(name: &'static str) -> Self {
+impl<F: FnPtr> DlsymWeak<F> {
+    /// # Safety
+    ///
+    /// If the signature of `F` does not match the signature of the symbol (if
+    /// it exists), calling the function pointer returned by `get()` is
+    /// undefined behaviour.
+    pub(crate) const unsafe fn new(name: &'static CStr) -> Self {
         DlsymWeak {
-            name,
+            name: name.as_ptr(),
             func: AtomicPtr::new(ptr::without_provenance_mut(1)),
             _marker: PhantomData,
         }
@@ -95,62 +126,59 @@ impl<F> DlsymWeak<F> {
 
     #[inline]
     pub(crate) fn get(&self) -> Option<F> {
-        unsafe {
-            // Relaxed is fine here because we fence before reading through the
-            // pointer (see the comment below).
-            match self.func.load(Ordering::Relaxed) {
-                func if func.addr() == 1 => self.initialize(),
-                func if func.is_null() => None,
-                func => {
-                    let func = mem::transmute_copy::<*mut libc::c_void, F>(&func);
-                    // The caller is presumably going to read through this value
-                    // (by calling the function we've dlsymed). This means we'd
-                    // need to have loaded it with at least C11's consume
-                    // ordering in order to be guaranteed that the data we read
-                    // from the pointer isn't from before the pointer was
-                    // stored. Rust has no equivalent to memory_order_consume,
-                    // so we use an acquire fence (sorry, ARM).
-                    //
-                    // Now, in practice this likely isn't needed even on CPUs
-                    // where relaxed and consume mean different things. The
-                    // symbols we're loading are probably present (or not) at
-                    // init, and even if they aren't the runtime dynamic loader
-                    // is extremely likely have sufficient barriers internally
-                    // (possibly implicitly, for example the ones provided by
-                    // invoking `mprotect`).
-                    //
-                    // That said, none of that's *guaranteed*, and so we fence.
-                    atomic::fence(Ordering::Acquire);
-                    Some(func)
-                }
-            }
+        // The caller is presumably going to read through this value
+        // (by calling the function we've dlsymed). This means we'd
+        // need to have loaded it with at least C11's consume
+        // ordering in order to be guaranteed that the data we read
+        // from the pointer isn't from before the pointer was
+        // stored. Rust has no equivalent to memory_order_consume,
+        // so we use an acquire load (sorry, ARM).
+        //
+        // Now, in practice this likely isn't needed even on CPUs
+        // where relaxed and consume mean different things. The
+        // symbols we're loading are probably present (or not) at
+        // init, and even if they aren't the runtime dynamic loader
+        // is extremely likely have sufficient barriers internally
+        // (possibly implicitly, for example the ones provided by
+        // invoking `mprotect`).
+        //
+        // That said, none of that's *guaranteed*, so we use acquire.
+        match self.func.load(Ordering::Acquire) {
+            func if func.addr() == 1 => self.initialize(),
+            func if func.is_null() => None,
+            // SAFETY:
+            // `func` is not null and `F` implements `FnPtr`, thus this
+            // transmutation is well-defined. It is the responsibility of the
+            // creator of this `DlsymWeak` to ensure that calling the resulting
+            // function pointer does not result in undefined behaviour (though
+            // the `dlsym!` macro delegates this responsibility to the caller
+            // of the function by using `unsafe` function pointers).
+            // FIXME: use `transmute` once it stops complaining about generics.
+            func => Some(unsafe { mem::transmute_copy::<*mut c_void, F>(&func) }),
         }
     }
 
     // Cold because it should only happen during first-time initialization.
     #[cold]
-    unsafe fn initialize(&self) -> Option<F> {
-        assert_eq!(size_of::<F>(), size_of::<*mut libc::c_void>());
-
-        let val = unsafe { fetch(self.name) };
-        // This synchronizes with the acquire fence in `get`.
+    fn initialize(&self) -> Option<F> {
+        // SAFETY: `self.name` was created from a `&'static CStr` and is
+        // therefore a valid C string pointer.
+        let val = unsafe { libc::dlsym(libc::RTLD_DEFAULT, self.name) };
+        // This synchronizes with the acquire load in `get`.
         self.func.store(val, Ordering::Release);
 
         if val.is_null() {
             None
         } else {
+            // SAFETY: see the comment in `get`.
+            // FIXME: use `transmute` once it stops complaining about generics.
             Some(unsafe { mem::transmute_copy::<*mut libc::c_void, F>(&val) })
         }
     }
 }
 
-unsafe fn fetch(name: &str) -> *mut libc::c_void {
-    let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
-        Ok(cstr) => cstr,
-        Err(..) => return ptr::null_mut(),
-    };
-    unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) }
-}
+unsafe impl<F> Send for DlsymWeak<F> {}
+unsafe impl<F> Sync for DlsymWeak<F> {}
 
 #[cfg(not(any(target_os = "linux", target_os = "android")))]
 pub(crate) macro syscall {
diff --git a/library/std/src/sys/pal/unix/weak/tests.rs b/library/std/src/sys/pal/unix/weak/tests.rs
new file mode 100644
index 00000000000..d807ba64e35
--- /dev/null
+++ b/library/std/src/sys/pal/unix/weak/tests.rs
@@ -0,0 +1,32 @@
+use super::*;
+
+#[test]
+fn dlsym_existing() {
+    const TEST_STRING: &'static CStr = c"Ferris!";
+
+    // Try to find a symbol that definitely exists.
+    dlsym! {
+        fn strlen(cs: *const c_char) -> usize;
+    }
+
+    dlsym! {
+        #[link_name = "strlen"]
+        fn custom_name(cs: *const c_char) -> usize;
+    }
+
+    let strlen = strlen.get().unwrap();
+    assert_eq!(unsafe { strlen(TEST_STRING.as_ptr()) }, TEST_STRING.count_bytes());
+
+    let custom_name = custom_name.get().unwrap();
+    assert_eq!(unsafe { custom_name(TEST_STRING.as_ptr()) }, TEST_STRING.count_bytes());
+}
+
+#[test]
+fn dlsym_missing() {
+    // Try to find a symbol that definitely does not exist.
+    dlsym! {
+        fn test_symbol_that_does_not_exist() -> i32;
+    }
+
+    assert!(test_symbol_that_does_not_exist.get().is_none());
+}
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index 49e15d65f25..17d99cdb385 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -276,7 +276,9 @@ fn wait(
             // If the managing thread happens to signal and unpark us before we
             // can park ourselves, the result could be this thread never gets
             // unparked. Luckily `park` comes with the guarantee that if it got
-            // an `unpark` just before on an unparked thread it does not park.
+            // an `unpark` just before on an unparked thread it does not park. Crucially, we know
+            // the `unpark` must have happened between the `compare_exchange_weak` above and here,
+            // and there's no other `park` in that code that could steal our token.
             // SAFETY: we retrieved this handle on the current thread above.
             unsafe { node.thread.park() }
         }
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 97b506c1b8f..4d09b2b4e9d 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1021,13 +1021,23 @@ impl Drop for PanicGuard {
 ///   specifying a maximum time to block the thread for.
 ///
 /// * The [`unpark`] method on a [`Thread`] atomically makes the token available
-///   if it wasn't already. Because the token is initially absent, [`unpark`]
-///   followed by [`park`] will result in the second call returning immediately.
-///
-/// The API is typically used by acquiring a handle to the current thread,
-/// placing that handle in a shared data structure so that other threads can
-/// find it, and then `park`ing in a loop. When some desired condition is met, another
-/// thread calls [`unpark`] on the handle.
+///   if it wasn't already. Because the token can be held by a thread even if it is currently not
+///   parked, [`unpark`] followed by [`park`] will result in the second call returning immediately.
+///   However, note that to rely on this guarantee, you need to make sure that your `unpark` happens
+///   after all `park` that may be done by other data structures!
+///
+/// The API is typically used by acquiring a handle to the current thread, placing that handle in a
+/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some
+/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point
+/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it
+/// will be woken up properly.
+///
+/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread
+/// without first establishing that it is about to be `park`ing within your code, that `unpark` may
+/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means
+/// you must not call unknown code between setting up for parking and calling `park`; for instance,
+/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a
+/// deadlock.
 ///
 /// The motivation for this design is twofold:
 ///
@@ -1058,21 +1068,24 @@ impl Drop for PanicGuard {
 ///
 /// ```
 /// use std::thread;
-/// use std::sync::{Arc, atomic::{Ordering, AtomicBool}};
+/// use std::sync::atomic::{Ordering, AtomicBool};
 /// use std::time::Duration;
 ///
-/// let flag = Arc::new(AtomicBool::new(false));
-/// let flag2 = Arc::clone(&flag);
+/// static QUEUED: AtomicBool = AtomicBool::new(false);
+/// static FLAG: AtomicBool = AtomicBool::new(false);
 ///
 /// let parked_thread = thread::spawn(move || {
+///     println!("Thread spawned");
+///     // Signal that we are going to `park`. Between this store and our `park`, there may
+///     // be no other `park`, or else that `park` could consume our `unpark` token!
+///     QUEUED.store(true, Ordering::Release);
 ///     // We want to wait until the flag is set. We *could* just spin, but using
 ///     // park/unpark is more efficient.
-///     while !flag2.load(Ordering::Relaxed) {
-///         println!("Parking thread");
+///     while !FLAG.load(Ordering::Acquire) {
+///         // We can *not* use `println!` here since that could use thread parking internally.
 ///         thread::park();
 ///         // We *could* get here spuriously, i.e., way before the 10ms below are over!
 ///         // But that is no problem, we are in a loop until the flag is set anyway.
-///         println!("Thread unparked");
 ///     }
 ///     println!("Flag received");
 /// });
@@ -1080,11 +1093,22 @@ impl Drop for PanicGuard {
 /// // Let some time pass for the thread to be spawned.
 /// thread::sleep(Duration::from_millis(10));
 ///
+/// // Ensure the thread is about to park.
+/// // This is crucial! It guarantees that the `unpark` below is not consumed
+/// // by some other code in the parked thread (e.g. inside `println!`).
+/// while !QUEUED.load(Ordering::Acquire) {
+///     // Spinning is of course inefficient; in practice, this would more likely be
+///     // a dequeue where we have no work to do if there's nobody queued.
+///     std::hint::spin_loop();
+/// }
+///
 /// // Set the flag, and let the thread wake up.
-/// // There is no race condition here, if `unpark`
+/// // There is no race condition here: if `unpark`
 /// // happens first, `park` will return immediately.
+/// // There is also no other `park` that could consume this token,
+/// // since we waited until the other thread got queued.
 /// // Hence there is no risk of a deadlock.
-/// flag.store(true, Ordering::Relaxed);
+/// FLAG.store(true, Ordering::Release);
 /// println!("Unpark the thread");
 /// parked_thread.thread().unpark();
 ///
@@ -1494,10 +1518,14 @@ impl Thread {
     /// ```
     /// use std::thread;
     /// use std::time::Duration;
+    /// use std::sync::atomic::{AtomicBool, Ordering};
+    ///
+    /// static QUEUED: AtomicBool = AtomicBool::new(false);
     ///
     /// let parked_thread = thread::Builder::new()
     ///     .spawn(|| {
     ///         println!("Parking thread");
+    ///         QUEUED.store(true, Ordering::Release);
     ///         thread::park();
     ///         println!("Thread unparked");
     ///     })
@@ -1506,6 +1534,15 @@ impl Thread {
     /// // Let some time pass for the thread to be spawned.
     /// thread::sleep(Duration::from_millis(10));
     ///
+    /// // Wait until the other thread is queued.
+    /// // This is crucial! It guarantees that the `unpark` below is not consumed
+    /// // by some other code in the parked thread (e.g. inside `println!`).
+    /// while !QUEUED.load(Ordering::Acquire) {
+    ///     // Spinning is of course inefficient; in practice, this would more likely be
+    ///     // a dequeue where we have no work to do if there's nobody queued.
+    ///     std::hint::spin_loop();
+    /// }
+    ///
     /// println!("Unpark the thread");
     /// parked_thread.thread().unpark();
     ///
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index ae889f1e778..2117f5f93ce 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -287,6 +287,8 @@ fn test_park_unpark_called_other_thread() {
     for _ in 0..10 {
         let th = thread::current();
 
+        // Here we rely on `thread::spawn` (specifically the part that runs after spawning
+        // the thread) to not consume the parking token.
         let _guard = thread::spawn(move || {
             super::sleep(Duration::from_millis(50));
             th.unpark();
@@ -316,6 +318,8 @@ fn test_park_timeout_unpark_called_other_thread() {
     for _ in 0..10 {
         let th = thread::current();
 
+        // Here we rely on `thread::spawn` (specifically the part that runs after spawning
+        // the thread) to not consume the parking token.
         let _guard = thread::spawn(move || {
             super::sleep(Duration::from_millis(50));
             th.unpark();
diff --git a/library/std/tests/sync/condvar.rs b/library/std/tests/sync/condvar.rs
index 1d712a64300..1b1c33efad5 100644
--- a/library/std/tests/sync/condvar.rs
+++ b/library/std/tests/sync/condvar.rs
@@ -17,7 +17,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: notify_one,
     test_body: {
@@ -38,7 +38,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: notify_all,
     test_body: {
@@ -79,7 +79,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: test_mutex_arc_condvar,
     test_body: {
@@ -116,7 +116,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_while,
     test_body: {
@@ -141,7 +141,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_timeout_wait,
     test_body: {
@@ -164,7 +164,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_timeout_while_wait,
     test_body: {
@@ -180,7 +180,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_timeout_while_instant_satisfy,
     test_body: {
@@ -197,7 +197,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_timeout_while_wake,
     test_body: {
@@ -226,7 +226,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
 nonpoison_and_poison_unwrap_test!(
     name: wait_timeout_wake,
     test_body: {
diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs
index ac1dbebcc5c..23112e10284 100644
--- a/library/std/tests/sync/lib.rs
+++ b/library/std/tests/sync/lib.rs
@@ -58,6 +58,9 @@ fn result_unwrap<T, E: std::fmt::Debug>(x: Result<T, E>) -> T {
 /// a no-op (the identity function).
 ///
 /// The test names will be prefiex with `poison_` or `nonpoison_`.
+///
+/// Important: most attributes (except `cfg`) will not work properly! (They are only applied to the first test.)
+/// See <https://github.com/rust-lang/rust/pull/146433> for more information.
 macro_rules! nonpoison_and_poison_unwrap_test {
     (
         name: $name:ident,
diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs
index 612c75c7aef..2445764001b 100644
--- a/library/std/tests/sync/mutex.rs
+++ b/library/std/tests/sync/mutex.rs
@@ -266,7 +266,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[cfg(panic = "unwind")] // Requires unwinding support.
 nonpoison_and_poison_unwrap_test!(
     name: test_panics,
     test_body: {
@@ -297,7 +297,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[cfg(panic = "unwind")] // Requires unwinding support.
 nonpoison_and_poison_unwrap_test!(
     name: test_mutex_arc_access_in_unwind,
     test_body: {
diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs
index eca15d2a4ad..65d8bac7194 100644
--- a/library/std/tests/sync/rwlock.rs
+++ b/library/std/tests/sync/rwlock.rs
@@ -50,7 +50,7 @@ nonpoison_and_poison_unwrap_test!(
 // FIXME: On macOS we use a provenance-incorrect implementation and Miri
 // catches that issue with a chance of around 1/1000.
 // See <https://github.com/rust-lang/rust/issues/121950> for details.
-#[cfg_attr(all(miri, target_os = "macos"), ignore)]
+#[cfg(not(all(miri, target_os = "macos")))]
 nonpoison_and_poison_unwrap_test!(
     name: frob,
     test_body: {
@@ -124,7 +124,7 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[cfg(panic = "unwind")] // Requires unwinding support.
 nonpoison_and_poison_unwrap_test!(
     name: test_rw_arc_access_in_unwind,
     test_body: {
@@ -315,7 +315,7 @@ nonpoison_and_poison_unwrap_test!(
 
 // FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
 // See <https://github.com/rust-lang/rust/issues/121950> for details.
-#[cfg_attr(all(miri, target_os = "macos"), ignore)]
+#[cfg(not(all(miri, target_os = "macos")))]
 nonpoison_and_poison_unwrap_test!(
     name: test_downgrade_observe,
     test_body: {
@@ -362,7 +362,7 @@ nonpoison_and_poison_unwrap_test!(
 
 // FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
 // See <https://github.com/rust-lang/rust/issues/121950> for details.
-#[cfg_attr(all(miri, target_os = "macos"), ignore)]
+#[cfg(not(all(miri, target_os = "macos")))]
 nonpoison_and_poison_unwrap_test!(
     name: test_downgrade_atomic,
     test_body: {
diff --git a/library/std_detect/src/detect/os/linux/aarch64.rs b/library/std_detect/src/detect/os/linux/aarch64.rs
index 87a9d6ebb88..b733b8a9eb2 100644
--- a/library/std_detect/src/detect/os/linux/aarch64.rs
+++ b/library/std_detect/src/detect/os/linux/aarch64.rs
@@ -140,7 +140,7 @@ struct AtHwcap {
 impl From<auxvec::AuxVec> for AtHwcap {
     /// Reads AtHwcap from the auxiliary vector.
     fn from(auxv: auxvec::AuxVec) -> Self {
-        AtHwcap {
+        let mut cap = AtHwcap {
             fp: bit::test(auxv.hwcap, 0),
             asimd: bit::test(auxv.hwcap, 1),
             // evtstrm: bit::test(auxv.hwcap, 2),
@@ -207,39 +207,50 @@ impl From<auxvec::AuxVec> for AtHwcap {
             // smef32f32: bit::test(auxv.hwcap2, 29),
             smefa64: bit::test(auxv.hwcap2, 30),
             wfxt: bit::test(auxv.hwcap2, 31),
-            // ebf16: bit::test(auxv.hwcap2, 32),
-            // sveebf16: bit::test(auxv.hwcap2, 33),
-            cssc: bit::test(auxv.hwcap2, 34),
-            // rprfm: bit::test(auxv.hwcap2, 35),
-            sve2p1: bit::test(auxv.hwcap2, 36),
-            sme2: bit::test(auxv.hwcap2, 37),
-            sme2p1: bit::test(auxv.hwcap2, 38),
-            // smei16i32: bit::test(auxv.hwcap2, 39),
-            // smebi32i32: bit::test(auxv.hwcap2, 40),
-            smeb16b16: bit::test(auxv.hwcap2, 41),
-            smef16f16: bit::test(auxv.hwcap2, 42),
-            mops: bit::test(auxv.hwcap2, 43),
-            hbc: bit::test(auxv.hwcap2, 44),
-            sveb16b16: bit::test(auxv.hwcap2, 45),
-            lrcpc3: bit::test(auxv.hwcap2, 46),
-            lse128: bit::test(auxv.hwcap2, 47),
-            fpmr: bit::test(auxv.hwcap2, 48),
-            lut: bit::test(auxv.hwcap2, 49),
-            faminmax: bit::test(auxv.hwcap2, 50),
-            f8cvt: bit::test(auxv.hwcap2, 51),
-            f8fma: bit::test(auxv.hwcap2, 52),
-            f8dp4: bit::test(auxv.hwcap2, 53),
-            f8dp2: bit::test(auxv.hwcap2, 54),
-            f8e4m3: bit::test(auxv.hwcap2, 55),
-            f8e5m2: bit::test(auxv.hwcap2, 56),
-            smelutv2: bit::test(auxv.hwcap2, 57),
-            smef8f16: bit::test(auxv.hwcap2, 58),
-            smef8f32: bit::test(auxv.hwcap2, 59),
-            smesf8fma: bit::test(auxv.hwcap2, 60),
-            smesf8dp4: bit::test(auxv.hwcap2, 61),
-            smesf8dp2: bit::test(auxv.hwcap2, 62),
-            // pauthlr: bit::test(auxv.hwcap2, ??),
+            ..Default::default()
+        };
+
+        // Hardware capabilities from bits 32 to 63 should only
+        // be tested on LP64 targets with 64 bits `usize`.
+        // On ILP32 targets like `aarch64-unknown-linux-gnu_ilp32`,
+        // these hardware capabilities will default to `false`.
+        // https://github.com/rust-lang/rust/issues/146230
+        #[cfg(target_pointer_width = "64")]
+        {
+            // cap.ebf16: bit::test(auxv.hwcap2, 32);
+            // cap.sveebf16: bit::test(auxv.hwcap2, 33);
+            cap.cssc = bit::test(auxv.hwcap2, 34);
+            // cap.rprfm: bit::test(auxv.hwcap2, 35);
+            cap.sve2p1 = bit::test(auxv.hwcap2, 36);
+            cap.sme2 = bit::test(auxv.hwcap2, 37);
+            cap.sme2p1 = bit::test(auxv.hwcap2, 38);
+            // cap.smei16i32 = bit::test(auxv.hwcap2, 39);
+            // cap.smebi32i32 = bit::test(auxv.hwcap2, 40);
+            cap.smeb16b16 = bit::test(auxv.hwcap2, 41);
+            cap.smef16f16 = bit::test(auxv.hwcap2, 42);
+            cap.mops = bit::test(auxv.hwcap2, 43);
+            cap.hbc = bit::test(auxv.hwcap2, 44);
+            cap.sveb16b16 = bit::test(auxv.hwcap2, 45);
+            cap.lrcpc3 = bit::test(auxv.hwcap2, 46);
+            cap.lse128 = bit::test(auxv.hwcap2, 47);
+            cap.fpmr = bit::test(auxv.hwcap2, 48);
+            cap.lut = bit::test(auxv.hwcap2, 49);
+            cap.faminmax = bit::test(auxv.hwcap2, 50);
+            cap.f8cvt = bit::test(auxv.hwcap2, 51);
+            cap.f8fma = bit::test(auxv.hwcap2, 52);
+            cap.f8dp4 = bit::test(auxv.hwcap2, 53);
+            cap.f8dp2 = bit::test(auxv.hwcap2, 54);
+            cap.f8e4m3 = bit::test(auxv.hwcap2, 55);
+            cap.f8e5m2 = bit::test(auxv.hwcap2, 56);
+            cap.smelutv2 = bit::test(auxv.hwcap2, 57);
+            cap.smef8f16 = bit::test(auxv.hwcap2, 58);
+            cap.smef8f32 = bit::test(auxv.hwcap2, 59);
+            cap.smesf8fma = bit::test(auxv.hwcap2, 60);
+            cap.smesf8dp4 = bit::test(auxv.hwcap2, 61);
+            cap.smesf8dp2 = bit::test(auxv.hwcap2, 62);
+            // cap.pauthlr = bit::test(auxv.hwcap2, ??);
         }
+        cap
     }
 }
 
diff --git a/package-lock.json b/package-lock.json
index def0cfa86a5..d0297bf70b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,7 +5,7 @@
   "packages": {
     "": {
       "dependencies": {
-        "browser-ui-test": "^0.22.0",
+        "browser-ui-test": "^0.22.2",
         "es-check": "^6.2.1",
         "eslint": "^8.57.1",
         "eslint-js": "github:eslint/js",
@@ -485,9 +485,9 @@
       }
     },
     "node_modules/browser-ui-test": {
-      "version": "0.22.0",
-      "resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.22.0.tgz",
-      "integrity": "sha512-p/C02TMybTDKsAjpGOdnyNC0Q25KDae/fKMnvHaqcJ0tXRqNKwndW2Ltq7HTmin5xqg8GGOmysEgWTZkXu6pfA==",
+      "version": "0.22.2",
+      "resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.22.2.tgz",
+      "integrity": "sha512-eNB/PN2yDGe5n5IwE3ld/N6A39jM1oRzJmT5nOVQqrvoZEtcd9JSggDQPNVUnMEyuGcD4OEOWMsEa4oJppAmDQ==",
       "license": "MIT",
       "dependencies": {
         "css-unit-converter": "^1.1.2",
diff --git a/package.json b/package.json
index 976d6303634..04e0f6af19a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "dependencies": {
-    "browser-ui-test": "^0.22.0",
+    "browser-ui-test": "^0.22.2",
     "es-check": "^6.2.1",
     "eslint": "^8.57.1",
     "eslint-js": "github:eslint/js",
diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml
index 9daf9faac14..b111a20f8d8 100644
--- a/src/bootstrap/defaults/bootstrap.dist.toml
+++ b/src/bootstrap/defaults/bootstrap.dist.toml
@@ -14,6 +14,10 @@ compiletest-use-stage0-libtest = false
 [llvm]
 download-ci-llvm = false
 
+# Most users installing from source want to build all parts of the project from source.
+[gcc]
+download-ci-gcc = false
+
 [rust]
 # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`).
 # Make sure they don't get set when installing from source.
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index 77c9622a9bf..717dea37e9e 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -32,6 +32,10 @@ pub struct GccOutput {
 impl GccOutput {
     /// Install the required libgccjit library file(s) to the specified `path`.
     pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) {
+        if builder.config.dry_run() {
+            return;
+        }
+
         // At build time, cg_gcc has to link to libgccjit.so (the unversioned symbol).
         // However, at runtime, it will by default look for libgccjit.so.0.
         // So when we install the built libgccjit.so file to the target `directory`, we add it there
@@ -39,8 +43,16 @@ impl GccOutput {
         let mut target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string();
         target_filename.push_str(".0");
 
+        // If we build libgccjit ourselves, then `self.libgccjit` can actually be a symlink.
+        // In that case, we have to resolve it first, otherwise we'd create a symlink to a symlink,
+        // which wouldn't work.
+        let actual_libgccjit_path = t!(
+            self.libgccjit.canonicalize(),
+            format!("Cannot find libgccjit at {}", self.libgccjit.display())
+        );
+
         let dst = directory.join(target_filename);
-        builder.copy_link(&self.libgccjit, &dst, FileType::NativeLibrary);
+        builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
     }
 }
 
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index 5999348a7fe..05a5dfc0bc5 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -422,10 +422,10 @@ impl std::str::FromStr for RustcLto {
 #[derive(Default, Clone)]
 pub enum GccCiMode {
     /// Build GCC from the local `src/gcc` submodule.
-    #[default]
     BuildLocally,
     /// Try to download GCC from CI.
     /// If it is not available on CI, it will be built locally instead.
+    #[default]
     DownloadFromCi,
 }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 01309072927..03b39882e30 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -541,4 +541,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "Added a new option `rust.break-on-ice` to control if internal compiler errors cause a debug break on Windows.",
     },
+    ChangeInfo {
+        change_id: 146435,
+        severity: ChangeSeverity::Info,
+        summary: "The default value of the `gcc.download-ci-gcc` option has been changed to `true`.",
+    },
 ];
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index b01b596da68..3b84ae2bed0 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -3639,7 +3639,7 @@ class DocSearch {
             if (contains.length === 0) {
                 return 0;
             }
-            const maxPathEditDistance = Math.floor(
+            const maxPathEditDistance = parsedQuery.literalSearch ? 0 : Math.floor(
                 contains.reduce((acc, next) => acc + next.length, 0) / 3,
             );
             let ret_dist = maxPathEditDistance + 1;
@@ -3650,7 +3650,9 @@ class DocSearch {
                 let dist_total = 0;
                 for (let x = 0; x < clength; ++x) {
                     const [p, c] = [path[i + x], contains[x]];
-                    if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance &&
+                    if (parsedQuery.literalSearch && p !== c) {
+                        continue pathiter;
+                    } else if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance &&
                         p.indexOf(c) !== -1
                     ) {
                         // discount distance on substring match
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index f70bdf4e4fe..06256d61151 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -17,7 +17,10 @@ use crate::core::DocContext;
 use crate::html::markdown::main_body_opts;
 
 pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) {
-    let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range<usize>| {
+    let report_diag = |cx: &DocContext<'_>,
+                       msg: &'static str,
+                       range: Range<usize>,
+                       without_brackets: Option<&str>| {
         let maybe_sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings)
             .map(|(sp, _)| sp);
         let sp = maybe_sp.unwrap_or_else(|| item.attr_span(cx.tcx));
@@ -27,14 +30,22 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
             // The fallback of using the attribute span is suitable for
             // highlighting where the error is, but not for placing the < and >
             if let Some(sp) = maybe_sp {
-                lint.multipart_suggestion(
-                    "use an automatic link instead",
-                    vec![
-                        (sp.shrink_to_lo(), "<".to_string()),
-                        (sp.shrink_to_hi(), ">".to_string()),
-                    ],
-                    Applicability::MachineApplicable,
-                );
+                if let Some(without_brackets) = without_brackets {
+                    lint.multipart_suggestion(
+                        "use an automatic link instead",
+                        vec![(sp, format!("<{without_brackets}>"))],
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    lint.multipart_suggestion(
+                        "use an automatic link instead",
+                        vec![
+                            (sp.shrink_to_lo(), "<".to_string()),
+                            (sp.shrink_to_hi(), ">".to_string()),
+                        ],
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
         });
     };
@@ -43,7 +54,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
 
     while let Some((event, range)) = p.next() {
         match event {
-            Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag),
+            Event::Text(s) => find_raw_urls(cx, dox, &s, range, &report_diag),
             // We don't want to check the text inside code blocks or links.
             Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => {
                 for (event, _) in p.by_ref() {
@@ -67,25 +78,35 @@ static URL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
         r"https?://",                          // url scheme
         r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
         r"[a-zA-Z]{2,63}",                     // root domain
-        r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)"      // optional query or url fragments
+        r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)",     // optional query or url fragments
     ))
     .expect("failed to build regex")
 });
 
 fn find_raw_urls(
     cx: &DocContext<'_>,
+    dox: &str,
     text: &str,
     range: Range<usize>,
-    f: &impl Fn(&DocContext<'_>, &'static str, Range<usize>),
+    f: &impl Fn(&DocContext<'_>, &'static str, Range<usize>, Option<&str>),
 ) {
     trace!("looking for raw urls in {text}");
     // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
     for match_ in URL_REGEX.find_iter(text) {
-        let url_range = match_.range();
-        f(
-            cx,
-            "this URL is not a hyperlink",
-            Range { start: range.start + url_range.start, end: range.start + url_range.end },
-        );
+        let mut url_range = match_.range();
+        url_range.start += range.start;
+        url_range.end += range.start;
+        let mut without_brackets = None;
+        // If the link is contained inside `[]`, then we need to replace the brackets and
+        // not just add `<>`.
+        if dox[..url_range.start].ends_with('[')
+            && url_range.end <= dox.len()
+            && dox[url_range.end..].starts_with(']')
+        {
+            url_range.start -= 1;
+            url_range.end += 1;
+            without_brackets = Some(match_.as_str());
+        }
+        f(cx, "this URL is not a hyperlink", url_range, without_brackets);
     }
 }
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 517aa343a6d..d433ee8daaa 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -606,6 +606,7 @@ Definite bugs found:
 * [A bug in the new `RwLock::downgrade` implementation](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/Miri.20error.20library.20test) (caught by Miri before it landed in the Rust repo)
 * [Mockall reading uninitialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite)
 * [`ReentrantLock` not correctly dealing with reuse of addresses for TLS storage of different threads](https://github.com/rust-lang/rust/pull/141248)
+* [Rare Deadlock in the thread (un)parking example code](https://github.com/rust-lang/rust/issues/145816)
 
 Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):
 
diff --git a/src/tools/tidy/src/extra_checks/mod.rs b/src/tools/tidy/src/extra_checks/mod.rs
index 321ef65117e..a6b50b5ca47 100644
--- a/src/tools/tidy/src/extra_checks/mod.rs
+++ b/src/tools/tidy/src/extra_checks/mod.rs
@@ -124,6 +124,12 @@ fn check_impl(
         };
     }
 
+    let rerun_with_bless = |mode: &str, action: &str| {
+        if !bless {
+            eprintln!("rerun tidy with `--extra-checks={mode} --bless` to {action}");
+        }
+    };
+
     let python_lint = extra_check!(Py, Lint);
     let python_fmt = extra_check!(Py, Fmt);
     let shell_lint = extra_check!(Shell, Lint);
@@ -147,14 +153,21 @@ fn check_impl(
     }
 
     if python_lint {
-        eprintln!("linting python files");
         let py_path = py_path.as_ref().unwrap();
-        let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &["check".as_ref()]);
+        let args: &[&OsStr] = if bless {
+            eprintln!("linting python files and applying suggestions");
+            &["check".as_ref(), "--fix".as_ref()]
+        } else {
+            eprintln!("linting python files");
+            &["check".as_ref()]
+        };
+
+        let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, args);
 
-        if res.is_err() && show_diff {
+        if res.is_err() && show_diff && !bless {
             eprintln!("\npython linting failed! Printing diff suggestions:");
 
-            let _ = run_ruff(
+            let diff_res = run_ruff(
                 root_path,
                 outdir,
                 py_path,
@@ -162,6 +175,10 @@ fn check_impl(
                 &file_args,
                 &["check".as_ref(), "--diff".as_ref()],
             );
+            // `ruff check --diff` will return status 0 if there are no suggestions.
+            if diff_res.is_err() {
+                rerun_with_bless("py:lint", "apply ruff suggestions");
+            }
         }
         // Rethrow error
         res?;
@@ -192,7 +209,7 @@ fn check_impl(
                     &["format".as_ref(), "--diff".as_ref()],
                 );
             }
-            eprintln!("rerun tidy with `--extra-checks=py:fmt --bless` to reformat Python code");
+            rerun_with_bless("py:fmt", "reformat Python code");
         }
 
         // Rethrow error
@@ -225,7 +242,7 @@ fn check_impl(
         let args = merge_args(&cfg_args_clang_format, &file_args_clang_format);
         let res = py_runner(py_path.as_ref().unwrap(), false, None, "clang-format", &args);
 
-        if res.is_err() && show_diff {
+        if res.is_err() && show_diff && !bless {
             eprintln!("\nclang-format linting failed! Printing diff suggestions:");
 
             let mut cfg_args_clang_format_diff = cfg_args.clone();
@@ -265,6 +282,7 @@ fn check_impl(
                     );
                 }
             }
+            rerun_with_bless("cpp:fmt", "reformat C++ code");
         }
         // Rethrow error
         res?;
@@ -290,12 +308,16 @@ fn check_impl(
         args.extend_from_slice(SPELLCHECK_DIRS);
 
         if bless {
-            eprintln!("spellcheck files and fix");
+            eprintln!("spellchecking files and fixing typos");
             args.push("--write-changes");
         } else {
-            eprintln!("spellcheck files");
+            eprintln!("spellchecking files");
         }
-        spellcheck_runner(root_path, &outdir, &cargo, &args)?;
+        let res = spellcheck_runner(root_path, &outdir, &cargo, &args);
+        if res.is_err() {
+            rerun_with_bless("spellcheck", "fix typos");
+        }
+        res?;
     }
 
     if js_lint || js_typecheck {
@@ -303,11 +325,21 @@ fn check_impl(
     }
 
     if js_lint {
-        rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless)?;
+        if bless {
+            eprintln!("linting javascript files");
+        } else {
+            eprintln!("linting javascript files and applying suggestions");
+        }
+        let res = rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless);
+        if res.is_err() {
+            rerun_with_bless("js:lint", "apply eslint suggestions");
+        }
+        res?;
         rustdoc_js::es_check(outdir, librustdoc_path)?;
     }
 
     if js_typecheck {
+        eprintln!("typechecking javascript files");
         rustdoc_js::typecheck(outdir, librustdoc_path)?;
     }
 
diff --git a/src/tools/tidy/src/extra_checks/rustdoc_js.rs b/src/tools/tidy/src/extra_checks/rustdoc_js.rs
index a6c66b8be80..5137e618367 100644
--- a/src/tools/tidy/src/extra_checks/rustdoc_js.rs
+++ b/src/tools/tidy/src/extra_checks/rustdoc_js.rs
@@ -57,7 +57,7 @@ fn run_eslint(
             if exit_status.success() {
                 return Ok(());
             }
-            Err(super::Error::FailedCheck("eslint command failed"))
+            Err(super::Error::FailedCheck("eslint"))
         }
         Err(error) => Err(super::Error::Generic(format!("eslint command failed: {error:?}"))),
     }
@@ -94,7 +94,7 @@ pub(super) fn typecheck(outdir: &Path, librustdoc_path: &Path) -> Result<(), sup
             if exit_status.success() {
                 return Ok(());
             }
-            Err(super::Error::FailedCheck("tsc command failed"))
+            Err(super::Error::FailedCheck("tsc"))
         }
         Err(error) => Err(super::Error::Generic(format!("tsc command failed: {error:?}"))),
     }
@@ -112,7 +112,7 @@ pub(super) fn es_check(outdir: &Path, librustdoc_path: &Path) -> Result<(), supe
             if exit_status.success() {
                 return Ok(());
             }
-            Err(super::Error::FailedCheck("es-check command failed"))
+            Err(super::Error::FailedCheck("es-check"))
         }
         Err(error) => Err(super::Error::Generic(format!("es-check command failed: {error:?}"))),
     }
diff --git a/tests/assembly-llvm/c-variadic-arm.rs b/tests/assembly-llvm/c-variadic-arm.rs
new file mode 100644
index 00000000000..2ef307405e1
--- /dev/null
+++ b/tests/assembly-llvm/c-variadic-arm.rs
@@ -0,0 +1,26 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -Copt-level=3
+//@ only-arm
+//@ ignore-thumb
+//@ ignore-android
+#![no_std]
+#![crate_type = "lib"]
+#![feature(c_variadic)]
+
+// Check that the assembly that rustc generates matches what clang emits.
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
+    // CHECK-LABEL: variadic
+    // CHECK: sub sp, sp
+
+    // CHECK: vldr
+    // CHECK: vadd.f64
+    // CHECK: vldr
+    // CHECK: vadd.f64
+    let b = args.arg::<f64>();
+    let c = args.arg::<f64>();
+    a + b + c
+
+    // CHECK: add sp, sp
+}
diff --git a/tests/codegen-llvm/c-variadic-lifetime.rs b/tests/codegen-llvm/c-variadic-lifetime.rs
new file mode 100644
index 00000000000..5b2f8af18c8
--- /dev/null
+++ b/tests/codegen-llvm/c-variadic-lifetime.rs
@@ -0,0 +1,21 @@
+//@ add-core-stubs
+//@ compile-flags: -Copt-level=3
+#![feature(c_variadic)]
+#![crate_type = "lib"]
+
+// Check that `%args` explicitly has its lifetime start and end. Being explicit can improve
+// instruction and register selection, see e.g. https://github.com/rust-lang/rust/pull/144549
+
+#[unsafe(no_mangle)]
+unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
+    // CHECK: call void @llvm.lifetime.start.p0(i64 {{[0-9]+}}, ptr nonnull %args)
+    // CHECK: call void @llvm.va_start.p0(ptr nonnull %args)
+
+    let b = args.arg::<f64>();
+    let c = args.arg::<f64>();
+
+    a + b + c
+
+    // CHECK: call void @llvm.va_end.p0(ptr nonnull %args)
+    // CHECK: call void @llvm.lifetime.end.p0(i64 {{[0-9]+}}, ptr nonnull %args)
+}
diff --git a/tests/rustdoc-js/literal-path.js b/tests/rustdoc-js/literal-path.js
new file mode 100644
index 00000000000..ea999ea1a6f
--- /dev/null
+++ b/tests/rustdoc-js/literal-path.js
@@ -0,0 +1,23 @@
+// exact-check
+
+// This test ensures that literal search is always applied on elements of the path.
+
+const EXPECTED = [
+    {
+        'query': '"some::path"',
+        'others': [
+            { 'path': 'literal_path::some', 'name': 'Path' },
+        ],
+    },
+    {
+        'query': '"somea::path"',
+        'others': [
+            { 'path': 'literal_path::somea', 'name': 'Path' },
+        ],
+    },
+    {
+        'query': '"soma::path"',
+        'others': [
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/literal-path.rs b/tests/rustdoc-js/literal-path.rs
new file mode 100644
index 00000000000..fa7685fd966
--- /dev/null
+++ b/tests/rustdoc-js/literal-path.rs
@@ -0,0 +1,7 @@
+pub mod some {
+    pub struct Path;
+}
+
+pub mod somea {
+    pub struct Path;
+}
diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed
index a91573146b8..ac63e291c5b 100644
--- a/tests/rustdoc-ui/lints/bare-urls.fixed
+++ b/tests/rustdoc-ui/lints/bare-urls.fixed
@@ -68,3 +68,17 @@ pub mod foo {
     /// https://somewhere.com/a?hello=12&bye=11#xyz
     pub fn bar() {}
 }
+
+/// <https://bloob.blob>
+//~^ ERROR this URL is not a hyperlink
+/// [ <https://bloob.blob> ]
+//~^ ERROR this URL is not a hyperlink
+/// [ <https://bloob.blob>]
+//~^ ERROR this URL is not a hyperlink
+/// [<https://bloob.blob> ]
+//~^ ERROR this URL is not a hyperlink
+/// [<https://bloob.blob>
+//~^ ERROR this URL is not a hyperlink
+/// <https://bloob.blob>]
+//~^ ERROR this URL is not a hyperlink
+pub fn lint_with_brackets() {}
diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs
index 5b008cdafa2..a70a3ec822e 100644
--- a/tests/rustdoc-ui/lints/bare-urls.rs
+++ b/tests/rustdoc-ui/lints/bare-urls.rs
@@ -68,3 +68,17 @@ pub mod foo {
     /// https://somewhere.com/a?hello=12&bye=11#xyz
     pub fn bar() {}
 }
+
+/// [https://bloob.blob]
+//~^ ERROR this URL is not a hyperlink
+/// [ https://bloob.blob ]
+//~^ ERROR this URL is not a hyperlink
+/// [ https://bloob.blob]
+//~^ ERROR this URL is not a hyperlink
+/// [https://bloob.blob ]
+//~^ ERROR this URL is not a hyperlink
+/// [https://bloob.blob
+//~^ ERROR this URL is not a hyperlink
+/// https://bloob.blob]
+//~^ ERROR this URL is not a hyperlink
+pub fn lint_with_brackets() {}
diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr
index e1108c7e7f8..fc3c642f5aa 100644
--- a/tests/rustdoc-ui/lints/bare-urls.stderr
+++ b/tests/rustdoc-ui/lints/bare-urls.stderr
@@ -243,5 +243,73 @@ help: use an automatic link instead
 LL | #[doc = "<https://example.com/raw>"]
    |          +                       +
 
-error: aborting due to 20 previous errors
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:72:5
+   |
+LL | /// [https://bloob.blob]
+   |     ^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://bloob.blob>`
+   |
+   = note: bare URLs are not automatically turned into clickable links
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:74:7
+   |
+LL | /// [ https://bloob.blob ]
+   |       ^^^^^^^^^^^^^^^^^^
+   |
+   = note: bare URLs are not automatically turned into clickable links
+help: use an automatic link instead
+   |
+LL | /// [ <https://bloob.blob> ]
+   |       +                  +
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:76:7
+   |
+LL | /// [ https://bloob.blob]
+   |       ^^^^^^^^^^^^^^^^^^
+   |
+   = note: bare URLs are not automatically turned into clickable links
+help: use an automatic link instead
+   |
+LL | /// [ <https://bloob.blob>]
+   |       +                  +
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:78:6
+   |
+LL | /// [https://bloob.blob ]
+   |      ^^^^^^^^^^^^^^^^^^
+   |
+   = note: bare URLs are not automatically turned into clickable links
+help: use an automatic link instead
+   |
+LL | /// [<https://bloob.blob> ]
+   |      +                  +
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:80:6
+   |
+LL | /// [https://bloob.blob
+   |      ^^^^^^^^^^^^^^^^^^
+   |
+   = note: bare URLs are not automatically turned into clickable links
+help: use an automatic link instead
+   |
+LL | /// [<https://bloob.blob>
+   |      +                  +
+
+error: this URL is not a hyperlink
+  --> $DIR/bare-urls.rs:82:5
+   |
+LL | /// https://bloob.blob]
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: bare URLs are not automatically turned into clickable links
+help: use an automatic link instead
+   |
+LL | /// <https://bloob.blob>]
+   |     +                  +
+
+error: aborting due to 26 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-sanitize.rs b/tests/ui/feature-gates/feature-gate-sanitize.rs
index 40098d93272..768417cfae8 100644
--- a/tests/ui/feature-gates/feature-gate-sanitize.rs
+++ b/tests/ui/feature-gates/feature-gate-sanitize.rs
@@ -1,4 +1,3 @@
-//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
 #![feature(no_sanitize)] //~ ERROR feature has been removed
 
 #[sanitize(address = "on")]
diff --git a/tests/ui/feature-gates/feature-gate-sanitize.stderr b/tests/ui/feature-gates/feature-gate-sanitize.stderr
index 7c38b351916..513999636a9 100644
--- a/tests/ui/feature-gates/feature-gate-sanitize.stderr
+++ b/tests/ui/feature-gates/feature-gate-sanitize.stderr
@@ -1,5 +1,5 @@
 error[E0557]: feature has been removed
-  --> $DIR/feature-gate-sanitize.rs:2:12
+  --> $DIR/feature-gate-sanitize.rs:1:12
    |
 LL | #![feature(no_sanitize)]
    |            ^^^^^^^^^^^ feature has been removed
@@ -8,7 +8,7 @@ LL | #![feature(no_sanitize)]
    = note: renamed to sanitize(xyz = "on|off")
 
 error[E0658]: the `#[sanitize]` attribute is an experimental feature
-  --> $DIR/feature-gate-sanitize.rs:4:1
+  --> $DIR/feature-gate-sanitize.rs:3:1
    |
 LL | #[sanitize(address = "on")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.next.stderr b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.next.stderr
new file mode 100644
index 00000000000..86ac1bdad04
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.next.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/avoid-inference-constraints-from-blanket-2.rs:27:18
+   |
+LL |     let _: u32 = x;
+   |            ---   ^ expected `u32`, found `u64`
+   |            |
+   |            expected due to this
+   |
+help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
+   |
+LL |     let _: u32 = x.try_into().unwrap();
+   |                   ++++++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.rs b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.rs
new file mode 100644
index 00000000000..b4f853de4aa
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-2.rs
@@ -0,0 +1,31 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] check-pass
+
+// Regression test for trait-system-refactor-initiative#205. Avoid
+// constraining other impl arguments when applying blanket impls.
+
+// FIXME(-Znext-solver): This currently incompletely constrains the
+// argument of `opaque: Trait<?x>` using the blanket impl of trait.
+// Ideally we don't do that.
+
+trait Trait<T> {}
+
+impl<T> Trait<u64> for T {}
+impl Trait<u32> for u64 {}
+
+fn impls_trait<T: Trait<U>, U>(_: U) -> T {
+    todo!()
+}
+
+fn foo() -> impl Sized {
+    let x = Default::default();
+    if false {
+        return impls_trait::<_, _>(x);
+    }
+    let _: u32 = x;
+    //[next]~^ ERROR mismatched types
+    1u64
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.rs b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.rs
new file mode 100644
index 00000000000..2f29cb4ee6b
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.rs
@@ -0,0 +1,25 @@
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+#![allow(unconditional_recursion)]
+
+// Regression test for trait-system-refactor-initiative#205. Avoid
+// constraining other impl arguments when applying blanket impls,
+// especially if the nested where-bounds of the blanket impl don't
+// actually apply for the opaque.
+
+// FIXME(-Znext-solver): This currently incompletely constrains the
+// argument of `opaque: Trait<?x>` using the blanket impl of trait.
+// Ideally we don't do that.
+
+trait Trait<T> {}
+
+impl<T: Copy> Trait<u32> for T {}
+impl Trait<u64> for String {}
+fn impls_trait<T: Trait<U>, U>(_: T) {}
+
+fn test() -> impl Sized {
+    let x = test();
+    impls_trait(x); //~ ERROR the trait bound `String: Trait<u32>` is not satisfied
+    String::new()
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.stderr b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.stderr
new file mode 100644
index 00000000000..a5d19b48481
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket-3.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `String: Trait<u32>` is not satisfied
+  --> $DIR/avoid-inference-constraints-from-blanket-3.rs:22:5
+   |
+LL |     impls_trait(x);
+   |     ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |
+   = help: the trait `Trait<u32>` is not implemented for `String`
+           but trait `Trait<u64>` is implemented for it
+   = help: for that trait implementation, expected `u64`, found `u32`
+note: required for `String` to implement `Trait<u32>`
+  --> $DIR/avoid-inference-constraints-from-blanket-3.rs:16:15
+   |
+LL | impl<T: Copy> Trait<u32> for T {}
+   |         ----  ^^^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required by a bound in `impls_trait`
+  --> $DIR/avoid-inference-constraints-from-blanket-3.rs:18:19
+   |
+LL | fn impls_trait<T: Trait<U>, U>(_: T) {}
+   |                   ^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket.rs b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket.rs
new file mode 100644
index 00000000000..bb3acfde5bc
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/avoid-inference-constraints-from-blanket.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#205. Avoid constraining
+// the opaque type when applying blanket impls.
+
+trait Trait<T> {}
+
+impl<T> Trait<T> for T {}
+impl Trait<u32> for u64 {}
+
+fn impls_trait<T: Trait<U>, U>() -> T {
+    todo!()
+}
+
+fn foo() -> impl Sized {
+    if false {
+        // `opaque: Trait<u32>` shouldn't constrain `opaque` to `u32` via the blanket impl
+        return impls_trait::<_, u32>();
+    }
+    1u64
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ambig.rs b/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ambig.rs
new file mode 100644
index 00000000000..e7aaf6fa135
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ambig.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+#![allow(unconditional_recursion)]
+
+// Regression test for trait-system-refactor-initiative#182. If multiple
+// opaque types result in different item bounds, do not apply them.
+
+trait Trait<T> {}
+impl<T, U> Trait<T> for U {}
+
+fn impls_trait<T: Trait<U>, U>(_: T) -> U {
+    todo!()
+}
+
+fn overlap<T, U>() -> (impl Trait<T>, impl Trait<U>) {
+    let mut x = overlap::<T, U>().0;
+    x = overlap::<T, U>().1;
+    let u = impls_trait(x);
+    let _: u32 = u;
+    ((), ())
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ok.rs b/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ok.rs
new file mode 100644
index 00000000000..d91efe181e3
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/multiple-opaques-ok.rs
@@ -0,0 +1,37 @@
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+#![allow(unconditional_recursion)]
+
+// Regression test for trait-system-refactor-initiative#18, making sure
+// we support being sub unified with more than 1 opaque type.
+
+trait Id {
+    type This;
+}
+impl Id for &'static str {
+    type This = &'static str;
+}
+fn to_assoc<T: Id>(x: T) -> <T as Id>::This {
+    todo!()
+}
+
+fn mirror1() -> (impl Id<This = &'static str>, impl Sized) {
+    let mut opaque = mirror1().0;
+    opaque = mirror1().1;
+    let x = to_assoc(opaque);
+    // `?x` equals both opaques, make sure we still use the applicable
+    // item bound.
+    x.len();
+    (x, x)
+}
+fn mirror2() -> (impl Sized, impl Id<This = &'static str>) {
+    let mut opaque = mirror2().0;
+    opaque = mirror2().1;
+    let x = to_assoc(opaque);
+    // `?x` equals both opaques, make sure we still use the applicable
+    // item bound.
+    x.len();
+    (x, x)
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/no-rigid-alias.rs b/tests/ui/impl-trait/non-defining-uses/no-rigid-alias.rs
new file mode 100644
index 00000000000..fca5db3e20f
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/no-rigid-alias.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+#![allow(unconditional_recursion)]
+
+// Test for trait-system-refactor-initiative#182 making sure
+// that we don't incorrectly normalize to rigid aliases if the
+// opaque type only has a trait bound.
+
+trait Id {
+    type This;
+}
+impl<T> Id for Vec<T> {
+    type This = Vec<T>;
+}
+fn to_assoc<T: Id>(x: T) -> <T as Id>::This {
+    todo!()
+}
+
+fn mirror<T>(x: Vec<T>) -> impl Id {
+    let x = to_assoc(mirror(x));
+    // `?x` equals `<opaque::<T> as Id>::This`. We should not infer `?x`
+    // to be a rigid alias here.
+    let _: Vec<u32> = x;
+    x
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs b/tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs
new file mode 100644
index 00000000000..50bb3995b94
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/use-blanket-impl.rs
@@ -0,0 +1,19 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#196.
+fn iterator(b: bool) -> impl Iterator<Item = String> {
+    if b {
+        // We need to eagerly figure out the type of `i` here by using
+        // the `<opaque as IntoIterator>::Item` obligation. This means
+        // we not only have to consider item bounds, but also blanket impls.
+        for i in iterator(false) {
+            i.len();
+        }
+    }
+
+    vec![].into_iter()
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/use-item-bound-over-blanket-impl.rs b/tests/ui/impl-trait/non-defining-uses/use-item-bound-over-blanket-impl.rs
new file mode 100644
index 00000000000..7c2766ade3f
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/use-item-bound-over-blanket-impl.rs
@@ -0,0 +1,30 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+#![allow(unconditional_recursion)]
+
+// Regression test for trait-system-refactor-initiative#182.
+
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+fn to_assoc<T>(x: T) -> <T as Id>::This {
+    x
+}
+
+fn mirror<T>(x: Vec<T>) -> impl Id<This = Vec<T>> {
+    let x = to_assoc(mirror(x));
+    // `?x` equals `<opaque::<T> as Id>::This`. We need to eagerly infer the
+    // type of `?x` to prevent this method call from resulting in an error.
+    //
+    // We could use both the item bound to normalize to `Vec<T>`, or the
+    // blanket impl to normalize to `opaque::<T>`. We have to go with the
+    // item bound.
+    x.len();
+    x
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/non-defining-uses/use-item-bound.rs b/tests/ui/impl-trait/non-defining-uses/use-item-bound.rs
new file mode 100644
index 00000000000..36dcbacbe6f
--- /dev/null
+++ b/tests/ui/impl-trait/non-defining-uses/use-item-bound.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+#![allow(unconditional_recursion)]
+// Regression test for trait-system-refactor-initiative#182.
+
+trait Id {
+    type This;
+}
+impl<T> Id for Vec<T> {
+    type This = Vec<T>;
+}
+fn to_assoc<T: Id>(x: T) -> <T as Id>::This {
+    todo!()
+}
+
+fn mirror<T>(x: Vec<T>) -> impl Id<This = Vec<T>> {
+    let x = to_assoc(mirror(x));
+    // `?x` equals `<opaque::<T> as Id>::This`. We need to eagerly infer the
+    // type of `?x` to prevent this method call from resulting in an error.
+    x.len();
+    x
+}
+fn main() {}
diff --git a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
index 695a752fe17..5ac50c943d0 100644
--- a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
+++ b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
@@ -92,6 +92,12 @@ macro_rules! combinations {
     }};
 }
 
+macro_rules! int_struct {
+    ($n: literal) => {
+        struct ${concat(E, $n)};
+    }
+}
+
 fn main() {
     create_things!(behold);
     behold_separated_idents_in_a_fn();
@@ -112,4 +118,16 @@ fn main() {
     assert_eq!(VAR_123, 2);
 
     combinations!(_hello, "a", b, "b");
+
+    int_struct!(1_0);
+    int_struct!(2);
+    int_struct!(3___0);
+    int_struct!(7_);
+    int_struct!(08);
+
+    let _ = E1_0;
+    let _ = E2;
+    let _ = E3___0;
+    let _ = E7_;
+    let _ = E08;
 }
diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs
index 7d8756de9e2..277ad240b1b 100644
--- a/tests/ui/macros/metavar-expressions/concat-usage-errors.rs
+++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.rs
@@ -140,7 +140,9 @@ macro_rules! bad_literal_non_string {
         //~| ERROR metavariables of `${concat(..)}` must be of type
         //~| ERROR metavariables of `${concat(..)}` must be of type
         //~| ERROR metavariables of `${concat(..)}` must be of type
-        //~| ERROR metavariables of `${concat(..)}` must be of type
+        //~| ERROR floats are not supported as metavariables of `${concat(..)}`
+        //~| ERROR integer metavariables of `${concat(..)}` must not be suffixed
+        //~| ERROR integer metavariables of `${concat(..)}` must not be suffixed
     }
 }
 
@@ -149,7 +151,6 @@ macro_rules! bad_tt_literal {
         const ${concat(_foo, $tt)}: () = ();
         //~^ ERROR metavariables of `${concat(..)}` must be of type
         //~| ERROR metavariables of `${concat(..)}` must be of type
-        //~| ERROR metavariables of `${concat(..)}` must be of type
     }
 }
 
@@ -178,13 +179,14 @@ fn main() {
     bad_literal_string!("1.0");
     bad_literal_string!("'1'");
 
-    bad_literal_non_string!(1);
     bad_literal_non_string!(-1);
     bad_literal_non_string!(1.0);
     bad_literal_non_string!('1');
     bad_literal_non_string!(false);
+    bad_literal_non_string!(4f64);
+    bad_literal_non_string!(5u8);
+    bad_literal_non_string!(6_u8);
 
-    bad_tt_literal!(1);
     bad_tt_literal!(1.0);
     bad_tt_literal!('1');
 }
diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr
index 8be3e792ec3..c124b76cb78 100644
--- a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr
+++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr
@@ -130,7 +130,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
 LL |         ${concat($ex, aaaa)}
    |                   ^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
 
 error: variable `foo` is not recognized in meta-variable expression
   --> $DIR/concat-usage-errors.rs:37:30
@@ -276,7 +276,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
 LL |         const ${concat(_foo, $literal)}: () = ();
    |                               ^^^^^^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
 
 error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
   --> $DIR/concat-usage-errors.rs:138:31
@@ -284,7 +284,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
 LL |         const ${concat(_foo, $literal)}: () = ();
    |                               ^^^^^^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
@@ -293,7 +293,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
 LL |         const ${concat(_foo, $literal)}: () = ();
    |                               ^^^^^^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
@@ -302,43 +302,45 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
 LL |         const ${concat(_foo, $literal)}: () = ();
    |                               ^^^^^^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
+error: floats are not supported as metavariables of `${concat(..)}`
   --> $DIR/concat-usage-errors.rs:138:31
    |
 LL |         const ${concat(_foo, $literal)}: () = ();
    |                               ^^^^^^^
+
+error: integer metavariables of `${concat(..)}` must not be suffixed
+  --> $DIR/concat-usage-errors.rs:138:31
    |
-   = note: currently only string literals are supported
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
 
-error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
-  --> $DIR/concat-usage-errors.rs:149:31
+error: integer metavariables of `${concat(..)}` must not be suffixed
+  --> $DIR/concat-usage-errors.rs:138:31
    |
-LL |         const ${concat(_foo, $tt)}: () = ();
-   |                               ^^
+LL |         const ${concat(_foo, $literal)}: () = ();
+   |                               ^^^^^^^
    |
-   = note: currently only string literals are supported
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
-  --> $DIR/concat-usage-errors.rs:149:31
+  --> $DIR/concat-usage-errors.rs:151:31
    |
 LL |         const ${concat(_foo, $tt)}: () = ();
    |                               ^^
    |
-   = note: currently only string literals are supported
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: currently only string and integer literals are supported
 
 error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
-  --> $DIR/concat-usage-errors.rs:149:31
+  --> $DIR/concat-usage-errors.rs:151:31
    |
 LL |         const ${concat(_foo, $tt)}: () = ();
    |                               ^^
    |
-   = note: currently only string literals are supported
+   = note: currently only string and integer literals are supported
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 43 previous errors
+error: aborting due to 44 previous errors