about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-02 23:49:08 +0000
committerbors <bors@rust-lang.org>2025-08-02 23:49:08 +0000
commit5b9564a18950db64c5aee8ba19d55a97b2e8d1cf (patch)
tree7025239244d0c2063e7ecb195a056fba7ae20bab
parenta65b04d7c9a1eaf02b62667da1c203c8a07976d9 (diff)
parent0fcfb8bee761b616bc36c88d2d48786a2789efba (diff)
downloadrust-5b9564a18950db64c5aee8ba19d55a97b2e8d1cf.tar.gz
rust-5b9564a18950db64c5aee8ba19d55a97b2e8d1cf.zip
Auto merge of #144814 - samueltardieu:rollup-qyum1hj, r=samueltardieu
Rollup of 17 pull requests

Successful merges:

 - rust-lang/rust#132748 (get rid of some false negatives in rustdoc::broken_intra_doc_links)
 - rust-lang/rust#143360 (loop match: error on `#[const_continue]` outside `#[loop_match]`)
 - rust-lang/rust#143662 ([rustdoc] Display unsafe attrs with edition 2024 `unsafe()` wrappers.)
 - rust-lang/rust#143771 (Constify some more `Result` functions)
 - rust-lang/rust#144185 (Document guarantees of poisoning)
 - rust-lang/rust#144395 (update fortanix tests)
 - rust-lang/rust#144478 (Improve formatting of doc code blocks)
 - rust-lang/rust#144614 (Fortify RemoveUnneededDrops test.)
 - rust-lang/rust#144703 ([test][AIX] ignore extern_weak linkage test)
 - rust-lang/rust#144747 (compiletest: Improve diagnostics for line annotation mismatches 2)
 - rust-lang/rust#144756 (detect infinite recursion with tail calls in ctfe)
 - rust-lang/rust#144766 (Add human readable name "Cygwin")
 - rust-lang/rust#144782 (Properly pass path to staged `rustc` to `compiletest` self-tests)
 - rust-lang/rust#144786 (Cleanup the definition of `group_type`)
 - rust-lang/rust#144796 (Add my previous commit name to .mailmap)
 - rust-lang/rust#144797 (Update safety comment for new_unchecked in niche_types)
 - rust-lang/rust#144803 (rustc-dev-guide subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--.mailmap1
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs61
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_hir/src/def.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/loops.rs50
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map.rs12
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs3
-rw-r--r--compiler/rustc_mir_build/messages.ftl2
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_operand.rs4
-rw-r--r--compiler/rustc_mir_build/src/errors.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs3
-rw-r--r--compiler/rustc_mir_transform/src/ctfe_limit.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drop.rs4
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_thread_pool/src/scope/mod.rs6
-rw-r--r--compiler/rustc_thread_pool/src/sleep/mod.rs2
-rw-r--r--library/alloc/src/string.rs4
-rw-r--r--library/alloc/src/vec/mod.rs10
-rw-r--r--library/core/src/cell.rs6
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/iter/traits/iterator.rs2
-rw-r--r--library/core/src/macros/mod.rs10
-rw-r--r--library/core/src/marker.rs3
-rw-r--r--library/core/src/mem/maybe_uninit.rs21
-rw-r--r--library/core/src/num/niche_types.rs6
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--library/core/src/result.rs139
-rw-r--r--library/coretests/tests/lib.rs2
-rw-r--r--library/coretests/tests/result.rs83
-rw-r--r--library/std/src/path.rs5
-rw-r--r--library/std/src/sync/once_lock.rs2
-rw-r--r--library/std/src/sync/poison.rs24
-rw-r--r--library/std/src/sync/poison/mutex.rs70
-rw-r--r--library/std/src/sync/poison/once.rs6
-rw-r--r--library/std/src/sync/poison/rwlock.rs10
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs6
-rw-r--r--src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml3
-rw-r--r--src/doc/rustc-dev-guide/rust-version2
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md1
-rw-r--r--src/doc/rustc-dev-guide/src/solve/candidate-preference.md427
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md5
-rw-r--r--src/doc/rustc-dev-guide/src/tests/docker.md15
-rw-r--r--src/doc/rustc-dev-guide/triagebot.toml3
-rw-r--r--src/librustdoc/clean/cfg.rs1
-rw-r--r--src/librustdoc/clean/types.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs32
-rw-r--r--src/tools/compiletest/src/directives/tests.rs18
-rw-r--r--src/tools/compiletest/src/runtest.rs37
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs31
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs14
-rw-r--r--tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs28
-rw-r--r--tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff15
-rw-r--r--tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff30
-rw-r--r--tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff15
-rw-r--r--tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff30
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff15
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff15
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff26
-rw-r--r--tests/mir-opt/remove_unneeded_drops.rs40
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs43
-rw-r--r--tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs30
-rw-r--r--tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr122
-rw-r--r--tests/rustdoc-ui/intra-doc/bad-intra-doc.rs15
-rw-r--r--tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr31
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.rs2
-rw-r--r--tests/rustdoc-ui/intra-doc/weird-syntax.stderr10
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs14
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr59
-rw-r--r--tests/rustdoc/attribute-rendering.rs6
-rw-r--r--tests/rustdoc/attributes-2021-edition.rs14
-rw-r--r--tests/rustdoc/attributes-re-export-2021-edition.rs13
-rw-r--r--tests/rustdoc/attributes-re-export.rs2
-rw-r--r--tests/rustdoc/attributes.rs13
-rw-r--r--tests/rustdoc/reexport/reexport-attrs.rs6
-rw-r--r--tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs10
-rw-r--r--tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr17
-rw-r--r--tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs1
-rw-r--r--tests/ui/loop-match/const-continue-to-block.rs21
-rw-r--r--tests/ui/loop-match/const-continue-to-block.stderr17
-rw-r--r--tests/ui/loop-match/invalid.rs19
-rw-r--r--tests/ui/loop-match/invalid.stderr22
92 files changed, 1500 insertions, 523 deletions
diff --git a/.mailmap b/.mailmap
index 90533e81b39..2b75f5a145f 100644
--- a/.mailmap
+++ b/.mailmap
@@ -597,6 +597,7 @@ Sam Radhakrishnan <sk09idm@gmail.com>
 Samuel Tardieu <sam@rfc1149.net>
 Santiago Pastorino <spastorino@gmail.com>
 Santiago Pastorino <spastorino@gmail.com> <santiago@wyeworks.com>
+Sasha Pourcelot <sasha.pourcelot@protonmail.com> Sasha <sasha.pourcelot@protonmail.com>
 Scott McMurray <scottmcm@users.noreply.github.com>
 Scott McMurray <scottmcm@users.noreply.github.com> <smcmurray@acm.org>
 Scott Olson <scott@solson.me> Scott Olson <scott@scott-olson.org>
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 54c0fbcd062..767d19bd234 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -62,15 +62,23 @@ use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
 use crate::parser::{ArgParser, MetaItemParser, PathParser};
 use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
 
-macro_rules! group_type {
-    ($stage: ty) => {
-         LazyLock<(
-            BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>,
-            Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>>
-        )>
-    };
+type GroupType<S> = LazyLock<GroupTypeInner<S>>;
+
+struct GroupTypeInner<S: Stage> {
+    accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
+    finalizers: Vec<FinalizeFn<S>>,
+}
+
+struct GroupTypeInnerAccept<S: Stage> {
+    template: AttributeTemplate,
+    accept_fn: AcceptFn<S>,
 }
 
+type AcceptFn<S> =
+    Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
+type FinalizeFn<S> =
+    Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
+
 macro_rules! attribute_parsers {
     (
         pub(crate) static $name: ident = [$($names: ty),* $(,)?];
@@ -93,11 +101,11 @@ macro_rules! attribute_parsers {
         }
     };
     (
-        @[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
+        @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
     ) => {
-        pub(crate) static $name: group_type!($ty) = LazyLock::new(|| {
-            let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new();
-            let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new();
+        pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
+            let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
+            let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
             $(
                 {
                     thread_local! {
@@ -105,11 +113,14 @@ macro_rules! attribute_parsers {
                     };
 
                     for (path, template, accept_fn) in <$names>::ATTRIBUTES {
-                        accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| {
-                            STATE_OBJECT.with_borrow_mut(|s| {
-                                accept_fn(s, cx, args)
+                        accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
+                            template: *template,
+                            accept_fn: Box::new(|cx, args| {
+                                STATE_OBJECT.with_borrow_mut(|s| {
+                                    accept_fn(s, cx, args)
+                                })
                             })
-                        })));
+                        });
                     }
 
                     finalizes.push(Box::new(|cx| {
@@ -119,7 +130,7 @@ macro_rules! attribute_parsers {
                 }
             )*
 
-            (accepts, finalizes)
+            GroupTypeInner { accepters:accepts, finalizers:finalizes }
         });
     };
 }
@@ -215,7 +226,7 @@ pub trait Stage: Sized + 'static + Sealed {
     type Id: Copy;
     const SHOULD_EMIT_LINTS: bool;
 
-    fn parsers() -> &'static group_type!(Self);
+    fn parsers() -> &'static GroupType<Self>;
 
     fn emit_err<'sess>(
         &self,
@@ -230,7 +241,7 @@ impl Stage for Early {
     type Id = NodeId;
     const SHOULD_EMIT_LINTS: bool = false;
 
-    fn parsers() -> &'static group_type!(Self) {
+    fn parsers() -> &'static GroupType<Self> {
         &early::ATTRIBUTE_PARSERS
     }
     fn emit_err<'sess>(
@@ -252,7 +263,7 @@ impl Stage for Late {
     type Id = HirId;
     const SHOULD_EMIT_LINTS: bool = true;
 
-    fn parsers() -> &'static group_type!(Self) {
+    fn parsers() -> &'static GroupType<Self> {
         &late::ATTRIBUTE_PARSERS
     }
     fn emit_err<'sess>(
@@ -811,8 +822,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                     let args = parser.args();
                     let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
 
-                    if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
-                        for (template, accept) in accepts {
+                    if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
+                        for accept in accepts {
                             let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
                                 shared: SharedContext {
                                     cx: self,
@@ -821,11 +832,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                                     emit_lint: &mut emit_lint,
                                 },
                                 attr_span: lower_span(attr.span),
-                                template,
+                                template: &accept.template,
                                 attr_path: path.get_attribute_path(),
                             };
 
-                            accept(&mut cx, args)
+                            (accept.accept_fn)(&mut cx, args)
                         }
                     } else {
                         // If we're here, we must be compiling a tool attribute... Or someone
@@ -856,7 +867,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
         }
 
         let mut parsed_attributes = Vec::new();
-        for f in &S::parsers().1 {
+        for f in &S::parsers().finalizers {
             if let Some(attr) = f(&mut FinalizeContext {
                 shared: SharedContext {
                     cx: self,
@@ -877,7 +888,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
 
     /// Returns whether there is a parser for an attribute with this name
     pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
-        Late::parsers().0.contains_key(path)
+        Late::parsers().accepters.contains_key(path)
     }
 
     fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 68f1637e07e..f1320048533 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -417,7 +417,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// minimum values.
     ///
     /// For example:
-    /// ```
+    /// ```ignore (illustrative)
     /// fn foo<'a, 'b>( /* ... */ ) where 'a: 'b { /* ... */ }
     /// ```
     /// would initialize two variables like so:
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 3fee9af01b3..2201d493f2d 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -360,7 +360,7 @@ impl DefKind {
 /// For example, everything prefixed with `/* Res */` in this example has
 /// an associated `Res`:
 ///
-/// ```
+/// ```ignore (illustrative)
 /// fn str_to_string(s: & /* Res */ str) -> /* Res */ String {
 ///     /* Res */ String::from(/* Res */ s)
 /// }
@@ -421,7 +421,7 @@ pub enum Res<Id = hir::HirId> {
     /// }
     ///
     /// impl Foo for Bar {
-    ///     fn foo() -> Box<Self> { // SelfTyAlias
+    ///     fn foo() -> Box<Self /* SelfTyAlias */> {
     ///         let _: Self;        // SelfTyAlias
     ///
     ///         todo!()
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 1b1b3ced44d..08361718108 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3016,7 +3016,7 @@ impl fmt::Display for LoopIdError {
     }
 }
 
-#[derive(Copy, Clone, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, PartialEq, HashStable_Generic)]
 pub struct Destination {
     /// This is `Some(_)` iff there is an explicit user-specified 'label
     pub label: Option<Label>,
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index e24426f9fed..bd9125363fc 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -425,7 +425,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateParam<'tcx> {
 ///
 /// trait Foo {
 ///     fn bar() -> impl Deref<Target = impl Sized>;
-///              // ^- RPITIT #1        ^- RPITIT #2
+///     //          ^- RPITIT #1        ^- RPITIT #2
 /// }
 ///
 /// impl Foo for () {
diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs
index d47a3246964..acfa5c473aa 100644
--- a/compiler/rustc_hir_typeck/src/loops.rs
+++ b/compiler/rustc_hir_typeck/src/loops.rs
@@ -2,7 +2,6 @@ use std::collections::BTreeMap;
 use std::fmt;
 
 use Context::*;
-use rustc_ast::Label;
 use rustc_hir as hir;
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::DefKind;
@@ -42,8 +41,8 @@ enum Context {
     ConstBlock,
     /// E.g. `#[loop_match] loop { state = 'label: { /* ... */ } }`.
     LoopMatch {
-        /// The label of the labeled block (not of the loop itself).
-        labeled_block: Label,
+        /// The destination pointing to the labeled block (not to the loop itself).
+        labeled_block: Destination,
     },
 }
 
@@ -186,18 +185,18 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
             {
                 self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b));
             }
-            hir::ExprKind::Break(break_label, ref opt_expr) => {
+            hir::ExprKind::Break(break_destination, ref opt_expr) => {
                 if let Some(e) = opt_expr {
                     self.visit_expr(e);
                 }
 
-                if self.require_label_in_labeled_block(e.span, &break_label, "break") {
+                if self.require_label_in_labeled_block(e.span, &break_destination, "break") {
                     // If we emitted an error about an unlabeled break in a labeled
                     // block, we don't need any further checking for this break any more
                     return;
                 }
 
-                let loop_id = match break_label.target_id {
+                let loop_id = match break_destination.target_id {
                     Ok(loop_id) => Some(loop_id),
                     Err(hir::LoopIdError::OutsideLoopScope) => None,
                     Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
@@ -212,18 +211,25 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
 
                 // A `#[const_continue]` must break to a block in a `#[loop_match]`.
                 if find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::ConstContinue(_)) {
-                    if let Some(break_label) = break_label.label {
-                        let is_target_label = |cx: &Context| match cx {
-                            Context::LoopMatch { labeled_block } => {
-                                break_label.ident.name == labeled_block.ident.name
-                            }
-                            _ => false,
-                        };
+                    let Some(label) = break_destination.label else {
+                        let span = e.span;
+                        self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span });
+                    };
 
-                        if !self.cx_stack.iter().rev().any(is_target_label) {
-                            let span = break_label.ident.span;
-                            self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span });
+                    let is_target_label = |cx: &Context| match cx {
+                        Context::LoopMatch { labeled_block } => {
+                            // NOTE: with macro expansion, the label's span might be different here
+                            // even though it does still refer to the same HIR node. A block
+                            // can't have two labels, so the hir_id is a unique identifier.
+                            assert!(labeled_block.target_id.is_ok()); // see `is_loop_match`.
+                            break_destination.target_id == labeled_block.target_id
                         }
+                        _ => false,
+                    };
+
+                    if !self.cx_stack.iter().rev().any(is_target_label) {
+                        let span = label.ident.span;
+                        self.tcx.dcx().emit_fatal(ConstContinueBadLabel { span });
                     }
                 }
 
@@ -249,7 +255,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
                         Some(kind) => {
                             let suggestion = format!(
                                 "break{}",
-                                break_label
+                                break_destination
                                     .label
                                     .map_or_else(String::new, |l| format!(" {}", l.ident))
                             );
@@ -259,7 +265,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
                                 kind: kind.name(),
                                 suggestion,
                                 loop_label,
-                                break_label: break_label.label,
+                                break_label: break_destination.label,
                                 break_expr_kind: &break_expr.kind,
                                 break_expr_span: break_expr.span,
                             });
@@ -268,7 +274,7 @@ impl<'hir> Visitor<'hir> for CheckLoopVisitor<'hir> {
                 }
 
                 let sp_lo = e.span.with_lo(e.span.lo() + BytePos("break".len() as u32));
-                let label_sp = match break_label.label {
+                let label_sp = match break_destination.label {
                     Some(label) => sp_lo.with_hi(label.ident.span.hi()),
                     None => sp_lo.shrink_to_lo(),
                 };
@@ -416,7 +422,7 @@ impl<'hir> CheckLoopVisitor<'hir> {
         &self,
         e: &'hir hir::Expr<'hir>,
         body: &'hir hir::Block<'hir>,
-    ) -> Option<Label> {
+    ) -> Option<Destination> {
         if !find_attr!(self.tcx.hir_attrs(e.hir_id), AttributeKind::LoopMatch(_)) {
             return None;
         }
@@ -438,8 +444,8 @@ impl<'hir> CheckLoopVisitor<'hir> {
 
         let hir::ExprKind::Assign(_, rhs_expr, _) = loop_body_expr.kind else { return None };
 
-        let hir::ExprKind::Block(_, label) = rhs_expr.kind else { return None };
+        let hir::ExprKind::Block(block, label) = rhs_expr.kind else { return None };
 
-        label
+        Some(Destination { label, target_id: Ok(block.hir_id) })
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index df38c3a1214..50fa3f2cc9d 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -2391,13 +2391,11 @@ fn migration_suggestion_for_2229(
 /// let mut p = Point { x: 10, y: 10 };
 ///
 /// let c = || {
-///     p.x     += 10;
-/// // ^ E1 ^
+///     p.x += 10; // E1
 ///     // ...
 ///     // More code
 ///     // ...
 ///     p.x += 10; // E2
-/// // ^ E2 ^
 /// };
 /// ```
 /// `CaptureKind` associated with both `E1` and `E2` will be ByRef(MutBorrow),
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index bb3b51c0ab2..b989d419057 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -36,7 +36,7 @@
 //! fn bar<T>(a: T, b: impl for<'a> Fn(&'a T)) {}
 //! fn foo<T>(x: T) {
 //!     bar(x, |y| { /* ... */})
-//!          // ^ closure arg
+//!     //      ^ closure arg
 //! }
 //! ```
 //!
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 3683d1e251c..4370816d38e 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -533,8 +533,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// ```
     /// fn foo(x: usize) -> bool {
     ///     if x == 1 {
-    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
-    ///     } else {  // to this, it will return `foo`'s `HirId`.
+    ///         // If `get_fn_id_for_return_block` gets passed the `id` corresponding to this, it
+    ///         // will return `foo`'s `HirId`.
+    ///         true
+    ///     } else {
     ///         false
     ///     }
     /// }
@@ -543,8 +545,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// ```compile_fail,E0308
     /// fn foo(x: usize) -> bool {
     ///     loop {
-    ///         true  // If `get_fn_id_for_return_block` gets passed the `id` corresponding
-    ///     }         // to this, it will return `None`.
+    ///         // If `get_fn_id_for_return_block` gets passed the `id` corresponding to this, it
+    ///         // will return `None`.
+    ///         true
+    ///     }
     ///     false
     /// }
     /// ```
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e819aa2d8f8..c55c7fc6002 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1017,7 +1017,8 @@ pub struct LocalDecl<'tcx> {
     /// ```
     /// fn foo(x: &str) {
     ///     #[allow(unused_mut)]
-    ///     let mut x: u32 = { // <- one unused mut
+    ///     let mut x: u32 = {
+    ///         //^ one unused mut
     ///         let mut y: u32 = x.parse().unwrap();
     ///         y + 2
     ///     };
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index abfe8eb66dd..287639de663 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -87,7 +87,7 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i
 mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]`
     .label = this value is too generic
 
-mir_build_const_continue_missing_value = a `#[const_continue]` must break to a label with a value
+mir_build_const_continue_missing_label_or_value = a `#[const_continue]` must break to a label with a value
 
 mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]`
     .help = try extracting the expression into a `const` item
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs
index 982e7aa8246..6a422223990 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs
@@ -57,7 +57,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// ```
     /// #![feature(unsized_fn_params)]
     /// # use core::fmt::Debug;
-    /// fn foo(_p: dyn Debug) { /* ... */ }
+    /// fn foo(_p: dyn Debug) {
+    ///     /* ... */
+    /// }
     ///
     /// fn bar(box_p: Box<dyn Debug>) { foo(*box_p); }
     /// ```
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index f1fbd5c4a49..1a52c6c85cb 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1254,8 +1254,8 @@ pub(crate) struct ConstContinueBadConst {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_const_continue_missing_value)]
-pub(crate) struct ConstContinueMissingValue {
+#[diag(mir_build_const_continue_missing_label_or_value)]
+pub(crate) struct ConstContinueMissingLabelOrValue {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index a0d3913c159..81b0e21a5f5 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -852,9 +852,9 @@ impl<'tcx> ThirBuildCx<'tcx> {
                 if find_attr!(self.tcx.hir_attrs(expr.hir_id), AttributeKind::ConstContinue(_)) {
                     match dest.target_id {
                         Ok(target_id) => {
-                            let Some(value) = value else {
+                            let (Some(value), Some(_)) = (value, dest.label) else {
                                 let span = expr.span;
-                                self.tcx.dcx().emit_fatal(ConstContinueMissingValue { span })
+                                self.tcx.dcx().emit_fatal(ConstContinueMissingLabelOrValue { span })
                             };
 
                             ExprKind::ConstContinue {
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index 117525eb777..5937d68f389 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -108,6 +108,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
 ///
 /// ```rust
 /// struct S;
+/// #[rustfmt::skip]
 /// fn foo(pred: bool) {                        // maybe-init:
 ///                                             // {}
 ///     let a = S; let mut b = S; let c; let d; // {a, b}
@@ -197,6 +198,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
 ///
 /// ```rust
 /// struct S;
+/// #[rustfmt::skip]
 /// fn foo(pred: bool) {                        // maybe-uninit:
 ///                                             // {a, b, c, d}
 ///     let a = S; let mut b = S; let c; let d; // {      c, d}
@@ -289,6 +291,7 @@ impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
 ///
 /// ```rust
 /// struct S;
+/// #[rustfmt::skip]
 /// fn foo(pred: bool) {                        // ever-init:
 ///                                             // {          }
 ///     let a = S; let mut b = S; let c; let d; // {a, b      }
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index fb17cca30f4..ac46336b834 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -18,7 +18,7 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
             .basic_blocks
             .iter_enumerated()
             .filter_map(|(node, node_data)| {
-                if matches!(node_data.terminator().kind, TerminatorKind::Call { .. })
+                if matches!(node_data.terminator().kind, TerminatorKind::Call { .. } | TerminatorKind::TailCall { .. })
                     // Back edges in a CFG indicate loops
                     || has_back_edge(doms, node, node_data)
                 {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs
index df4853c1dcb..4f3c53d761f 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drop.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs
@@ -611,6 +611,7 @@ where
     ///
     /// For example, with 3 fields, the drop ladder is
     ///
+    /// ```text
     /// .d0:
     ///     ELAB(drop location.0 [target=.d1, unwind=.c1])
     /// .d1:
@@ -621,8 +622,10 @@ where
     ///     ELAB(drop location.1 [target=.c2])
     /// .c2:
     ///     ELAB(drop location.2 [target=`self.unwind`])
+    /// ```
     ///
     /// For possible-async drops in coroutines we also need dropline ladder
+    /// ```text
     /// .d0 (mainline):
     ///     ELAB(drop location.0 [target=.d1, unwind=.c1, drop=.e1])
     /// .d1 (mainline):
@@ -637,6 +640,7 @@ where
     ///     ELAB(drop location.1 [target=.e2, unwind=.c2])
     /// .e2 (dropline):
     ///     ELAB(drop location.2 [target=`self.drop`, unwind=`self.unwind`])
+    /// ```
     ///
     /// NOTE: this does not clear the master drop flag, so you need
     /// to point succ/unwind on a `drop_ladder_bottom`.
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 97d1d9c2d2a..19494ffc37e 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -768,7 +768,9 @@ impl SyntaxContext {
     ///
     /// ```rust
     /// #![feature(decl_macro)]
-    /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty.
+    /// mod foo {
+    ///     pub fn f() {} // `f`'s `SyntaxContext` is empty.
+    /// }
     /// m!(f);
     /// macro m($f:ident) {
     ///     mod bar {
diff --git a/compiler/rustc_thread_pool/src/scope/mod.rs b/compiler/rustc_thread_pool/src/scope/mod.rs
index 38230383965..677009a9bc3 100644
--- a/compiler/rustc_thread_pool/src/scope/mod.rs
+++ b/compiler/rustc_thread_pool/src/scope/mod.rs
@@ -501,9 +501,9 @@ impl<'scope> Scope<'scope> {
     /// let mut value_c = None;
     /// rayon::scope(|s| {
     ///     s.spawn(|s1| {
-    ///           // ^ this is the same scope as `s`; this handle `s1`
-    ///           //   is intended for use by the spawned task,
-    ///           //   since scope handles cannot cross thread boundaries.
+    ///         //   ^ this is the same scope as `s`; this handle `s1`
+    ///         //     is intended for use by the spawned task,
+    ///         //     since scope handles cannot cross thread boundaries.
     ///
     ///         value_a = Some(22);
     ///
diff --git a/compiler/rustc_thread_pool/src/sleep/mod.rs b/compiler/rustc_thread_pool/src/sleep/mod.rs
index 31bf7184b42..aa666609214 100644
--- a/compiler/rustc_thread_pool/src/sleep/mod.rs
+++ b/compiler/rustc_thread_pool/src/sleep/mod.rs
@@ -44,7 +44,7 @@ impl SleepData {
 /// jobs are published, and it either blocks threads or wakes them in response to these
 /// events. See the [`README.md`] in this module for more details.
 ///
-/// [`README.md`] README.md
+/// [`README.md`]: README.md
 pub(super) struct Sleep {
     /// One "sleep state" per worker. Used to track if a worker is sleeping and to have
     /// them block.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index d58240f3051..9eacbf00e42 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -265,12 +265,12 @@ use crate::vec::{self, Vec};
 /// You can look at these with the [`as_ptr`], [`len`], and [`capacity`]
 /// methods:
 ///
+// FIXME Update this when vec_into_raw_parts is stabilized
 /// ```
 /// use std::mem;
 ///
 /// let story = String::from("Once upon a time...");
 ///
-// FIXME Update this when vec_into_raw_parts is stabilized
 /// // Prevent automatically dropping the String's data
 /// let mut story = mem::ManuallyDrop::new(story);
 ///
@@ -970,13 +970,13 @@ impl String {
     ///
     /// # Examples
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// ```
     /// use std::mem;
     ///
     /// unsafe {
     ///     let s = String::from("hello");
     ///
-    // FIXME Update this when vec_into_raw_parts is stabilized
     ///     // Prevent automatically dropping the String's data
     ///     let mut s = mem::ManuallyDrop::new(s);
     ///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index ce74615dbcc..2321aab2c51 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -566,13 +566,13 @@ impl<T> Vec<T> {
     ///
     /// # Examples
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// ```
     /// use std::ptr;
     /// use std::mem;
     ///
     /// let v = vec![1, 2, 3];
     ///
-    // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
     /// // of the allocation.
     /// let mut v = mem::ManuallyDrop::new(v);
@@ -674,6 +674,7 @@ impl<T> Vec<T> {
     ///
     /// # Examples
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// ```
     /// #![feature(box_vec_non_null)]
     ///
@@ -682,7 +683,6 @@ impl<T> Vec<T> {
     ///
     /// let v = vec![1, 2, 3];
     ///
-    // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
     /// // of the allocation.
     /// let mut v = mem::ManuallyDrop::new(v);
@@ -994,6 +994,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// # Examples
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// ```
     /// #![feature(allocator_api)]
     ///
@@ -1007,7 +1008,6 @@ impl<T, A: Allocator> Vec<T, A> {
     /// v.push(2);
     /// v.push(3);
     ///
-    // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
     /// // of the allocation.
     /// let mut v = mem::ManuallyDrop::new(v);
@@ -1114,6 +1114,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// # Examples
     ///
+    // FIXME Update this when vec_into_raw_parts is stabilized
     /// ```
     /// #![feature(allocator_api, box_vec_non_null)]
     ///
@@ -1127,7 +1128,6 @@ impl<T, A: Allocator> Vec<T, A> {
     /// v.push(2);
     /// v.push(3);
     ///
-    // FIXME Update this when vec_into_raw_parts is stabilized
     /// // Prevent running `v`'s destructor so we are in complete control
     /// // of the allocation.
     /// let mut v = mem::ManuallyDrop::new(v);
@@ -3872,8 +3872,8 @@ impl<T, A: Allocator> Vec<T, A> {
     /// while i < vec.len() - end_items {
     ///     if some_predicate(&mut vec[i]) {
     ///         let val = vec.remove(i);
-    /// #         extracted.push(val);
     ///         // your code here
+    /// #         extracted.push(val);
     ///     } else {
     ///         i += 1;
     ///     }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index d6d1bf2effa..d67408cae1b 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2068,9 +2068,9 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 /// implies exclusive access to its `T`:
 ///
 /// ```rust
-/// #![forbid(unsafe_code)] // with exclusive accesses,
-///                         // `UnsafeCell` is a transparent no-op wrapper,
-///                         // so no need for `unsafe` here.
+/// #![forbid(unsafe_code)]
+/// // with exclusive accesses, `UnsafeCell` is a transparent no-op wrapper, so no need for
+/// // `unsafe` here.
 /// use std::cell::UnsafeCell;
 ///
 /// let mut x: UnsafeCell<i32> = 42.into();
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 696d323c66d..c72eeb9a9c9 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -649,8 +649,6 @@ pub const fn must_use<T>(value: T) -> T {
 ///     }
 /// }
 /// ```
-///
-///
 #[unstable(feature = "likely_unlikely", issue = "136873")]
 #[inline(always)]
 pub const fn likely(b: bool) -> bool {
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 7ca41d224a0..56ca1305b60 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -233,10 +233,12 @@
 //!
 //! ```
 //! let mut values = vec![41];
-//! for x in &mut values { // same as `values.iter_mut()`
+//! for x in &mut values {
+//!     //   ^ same as `values.iter_mut()`
 //!     *x += 1;
 //! }
-//! for x in &values { // same as `values.iter()`
+//! for x in &values {
+//!     //   ^ same as `values.iter()`
 //!     assert_eq!(*x, 42);
 //! }
 //! assert_eq!(values.len(), 1);
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 10f9d464f7d..29313867ff2 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -807,7 +807,7 @@ pub trait Iterator {
     /// might be preferable to keep a functional style with longer iterators:
     ///
     /// ```
-    /// (0..5).flat_map(|x| x * 100 .. x * 110)
+    /// (0..5).flat_map(|x| (x * 100)..(x * 110))
     ///       .enumerate()
     ///       .filter(|&(i, x)| (i + x) % 3 == 0)
     ///       .for_each(|(i, x)| println!("{i}:{x}"));
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 3d57da63683..c59290a757b 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -271,7 +271,10 @@ pub macro cfg_select($($tt:tt)*) {
 /// // expression given.
 /// debug_assert!(true);
 ///
-/// fn some_expensive_computation() -> bool { true } // a very simple function
+/// fn some_expensive_computation() -> bool {
+///     // Some expensive computation here
+///     true
+/// }
 /// debug_assert!(some_expensive_computation());
 ///
 /// // assert with a custom message
@@ -1547,7 +1550,10 @@ pub(crate) mod builtin {
     /// // expression given.
     /// assert!(true);
     ///
-    /// fn some_computation() -> bool { true } // a very simple function
+    /// fn some_computation() -> bool {
+    ///     // Some expensive computation here
+    ///     true
+    /// }
     ///
     /// assert!(some_computation());
     ///
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 45277a1c82d..ba00ee17b65 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -138,8 +138,7 @@ unsafe impl<T: Sync + PointeeSized> Send for &T {}
 /// impl Bar for Impl { }
 ///
 /// let x: &dyn Foo = &Impl;    // OK
-/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
-///                             // be made into an object
+/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot be made into an object
 /// ```
 ///
 /// [trait object]: ../../book/ch17-02-trait-objects.html
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 34d8370da7e..c160360cfac 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -773,8 +773,7 @@ impl<T> MaybeUninit<T> {
     /// // Initialize the `MaybeUninit` using `Cell::set`:
     /// unsafe {
     ///     b.assume_init_ref().set(true);
-    ///    // ^^^^^^^^^^^^^^^
-    ///    // Reference to an uninitialized `Cell<bool>`: UB!
+    ///     //^^^^^^^^^^^^^^^ Reference to an uninitialized `Cell<bool>`: UB!
     /// }
     /// ```
     #[stable(feature = "maybe_uninit_ref", since = "1.55.0")]
@@ -864,9 +863,9 @@ impl<T> MaybeUninit<T> {
     /// {
     ///     let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
     ///     reader.read_exact(unsafe { buffer.assume_init_mut() })?;
-    ///                             // ^^^^^^^^^^^^^^^^^^^^^^^^
-    ///                             // (mutable) reference to uninitialized memory!
-    ///                             // This is undefined behavior.
+    ///     //                         ^^^^^^^^^^^^^^^^^^^^^^^^
+    ///     // (mutable) reference to uninitialized memory!
+    ///     // This is undefined behavior.
     ///     Ok(unsafe { buffer.assume_init() })
     /// }
     /// ```
@@ -884,13 +883,13 @@ impl<T> MaybeUninit<T> {
     /// let foo: Foo = unsafe {
     ///     let mut foo = MaybeUninit::<Foo>::uninit();
     ///     ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337);
-    ///                  // ^^^^^^^^^^^^^^^^^^^^^
-    ///                  // (mutable) reference to uninitialized memory!
-    ///                  // This is undefined behavior.
+    ///     //              ^^^^^^^^^^^^^^^^^^^^^
+    ///     // (mutable) reference to uninitialized memory!
+    ///     // This is undefined behavior.
     ///     ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42);
-    ///                  // ^^^^^^^^^^^^^^^^^^^^^
-    ///                  // (mutable) reference to uninitialized memory!
-    ///                  // This is undefined behavior.
+    ///     //              ^^^^^^^^^^^^^^^^^^^^^
+    ///     // (mutable) reference to uninitialized memory!
+    ///     // This is undefined behavior.
     ///     foo.assume_init()
     /// };
     /// ```
diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs
index b92561c9e35..d57b1d433e5 100644
--- a/library/core/src/num/niche_types.rs
+++ b/library/core/src/num/niche_types.rs
@@ -46,11 +46,11 @@ macro_rules! define_valid_range_type {
             /// primitive without checking whether its zero.
             ///
             /// # Safety
-            /// Immediate language UB if `val == 0`, as it violates the validity
-            /// invariant of this type.
+            /// Immediate language UB if `val` is not within the valid range for this
+            /// type, as it violates the validity invariant.
             #[inline]
             pub const unsafe fn new_unchecked(val: $int) -> Self {
-                // SAFETY: Caller promised that `val` is non-zero.
+                // SAFETY: Caller promised that `val` is within the valid range.
                 unsafe { $name(val) }
             }
 
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 9a1ba7d1728..1c824e336be 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -271,6 +271,7 @@ mod prim_bool {}
 /// When the compiler sees a value of type `!` in a [coercion site], it implicitly inserts a
 /// coercion to allow the type checker to infer any type:
 ///
+// FIXME: use `core::convert::absurd` here instead, once it's merged
 /// ```rust,ignore (illustrative-and-has-placeholders)
 /// // this
 /// let x: u8 = panic!();
@@ -281,7 +282,6 @@ mod prim_bool {}
 /// // where absurd is a function with the following signature
 /// // (it's sound, because `!` always marks unreachable code):
 /// fn absurd<T>(_: !) -> T { ... }
-// FIXME: use `core::convert::absurd` here instead, once it's merged
 /// ```
 ///
 /// This can lead to compilation errors if the type cannot be inferred:
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index f65257ff59b..474f86395ae 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -534,6 +534,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::iter::{self, FusedIterator, TrustedLen};
+use crate::marker::Destruct;
 use crate::ops::{self, ControlFlow, Deref, DerefMut};
 use crate::{convert, fmt, hint};
 
@@ -606,7 +607,13 @@ impl<T, E> Result<T, E> {
     #[must_use]
     #[inline]
     #[stable(feature = "is_some_and", since = "1.70.0")]
-    pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn is_ok_and<F>(self, f: F) -> bool
+    where
+        F: ~const FnOnce(T) -> bool + ~const Destruct,
+        T: ~const Destruct,
+        E: ~const Destruct,
+    {
         match self {
             Err(_) => false,
             Ok(x) => f(x),
@@ -655,7 +662,13 @@ impl<T, E> Result<T, E> {
     #[must_use]
     #[inline]
     #[stable(feature = "is_some_and", since = "1.70.0")]
-    pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn is_err_and<F>(self, f: F) -> bool
+    where
+        F: ~const FnOnce(E) -> bool + ~const Destruct,
+        E: ~const Destruct,
+        T: ~const Destruct,
+    {
         match self {
             Ok(_) => false,
             Err(e) => f(e),
@@ -682,8 +695,13 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
     #[rustc_diagnostic_item = "result_ok_method"]
-    pub fn ok(self) -> Option<T> {
+    pub const fn ok(self) -> Option<T>
+    where
+        T: ~const Destruct,
+        E: ~const Destruct,
+    {
         match self {
             Ok(x) => Some(x),
             Err(_) => None,
@@ -706,7 +724,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn err(self) -> Option<E> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn err(self) -> Option<E>
+    where
+        T: ~const Destruct,
+        E: ~const Destruct,
+    {
         match self {
             Ok(_) => None,
             Err(x) => Some(x),
@@ -796,7 +819,11 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn map<U, F>(self, op: F) -> Result<U, E>
+    where
+        F: ~const FnOnce(T) -> U + ~const Destruct,
+    {
         match self {
             Ok(t) => Ok(op(t)),
             Err(e) => Err(e),
@@ -823,8 +850,15 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_map_or", since = "1.41.0")]
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
     #[must_use = "if you don't need the returned value, use `if let` instead"]
-    pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
+    pub const fn map_or<U, F>(self, default: U, f: F) -> U
+    where
+        F: ~const FnOnce(T) -> U + ~const Destruct,
+        T: ~const Destruct,
+        E: ~const Destruct,
+        U: ~const Destruct,
+    {
         match self {
             Ok(t) => f(t),
             Err(_) => default,
@@ -851,7 +885,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_map_or_else", since = "1.41.0")]
-    pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn map_or_else<U, D, F>(self, default: D, f: F) -> U
+    where
+        D: ~const FnOnce(E) -> U + ~const Destruct,
+        F: ~const FnOnce(T) -> U + ~const Destruct,
+    {
         match self {
             Ok(t) => f(t),
             Err(e) => default(e),
@@ -877,10 +916,13 @@ impl<T, E> Result<T, E> {
     /// [default value]: Default::default
     #[inline]
     #[unstable(feature = "result_option_map_or_default", issue = "138099")]
-    pub fn map_or_default<U, F>(self, f: F) -> U
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn map_or_default<U, F>(self, f: F) -> U
     where
-        U: Default,
-        F: FnOnce(T) -> U,
+        F: ~const FnOnce(T) -> U + ~const Destruct,
+        U: ~const Default,
+        T: ~const Destruct,
+        E: ~const Destruct,
     {
         match self {
             Ok(t) => f(t),
@@ -908,7 +950,11 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn map_err<F, O>(self, op: O) -> Result<T, F>
+    where
+        O: ~const FnOnce(E) -> F + ~const Destruct,
+    {
         match self {
             Ok(t) => Ok(t),
             Err(e) => Err(op(e)),
@@ -930,7 +976,11 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_option_inspect", since = "1.76.0")]
-    pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn inspect<F>(self, f: F) -> Self
+    where
+        F: ~const FnOnce(&T) + ~const Destruct,
+    {
         if let Ok(ref t) = self {
             f(t);
         }
@@ -954,7 +1004,11 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "result_option_inspect", since = "1.76.0")]
-    pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn inspect_err<F>(self, f: F) -> Self
+    where
+        F: ~const FnOnce(&E) + ~const Destruct,
+    {
         if let Err(ref e) = self {
             f(e);
         }
@@ -1033,7 +1087,8 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<'_, T> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn iter(&self) -> Iter<'_, T> {
         Iter { inner: self.as_ref().ok() }
     }
 
@@ -1056,7 +1111,8 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn iter_mut(&mut self) -> IterMut<'_, T> {
         IterMut { inner: self.as_mut().ok() }
     }
 
@@ -1195,9 +1251,11 @@ impl<T, E> Result<T, E> {
     /// [`FromStr`]: crate::str::FromStr
     #[inline]
     #[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
-    pub fn unwrap_or_default(self) -> T
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn unwrap_or_default(self) -> T
     where
-        T: Default,
+        T: ~const Default + ~const Destruct,
+        E: ~const Destruct,
     {
         match self {
             Ok(x) => x,
@@ -1370,7 +1428,13 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn and<U>(self, res: Result<U, E>) -> Result<U, E>
+    where
+        T: ~const Destruct,
+        E: ~const Destruct,
+        U: ~const Destruct,
+    {
         match self {
             Ok(_) => res,
             Err(e) => Err(e),
@@ -1409,8 +1473,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
     #[rustc_confusables("flat_map", "flatmap")]
-    pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
+    pub const fn and_then<U, F>(self, op: F) -> Result<U, E>
+    where
+        F: ~const FnOnce(T) -> Result<U, E> + ~const Destruct,
+    {
         match self {
             Ok(t) => op(t),
             Err(e) => Err(e),
@@ -1446,7 +1514,13 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn or<F>(self, res: Result<T, F>) -> Result<T, F>
+    where
+        T: ~const Destruct,
+        E: ~const Destruct,
+        F: ~const Destruct,
+    {
         match self {
             Ok(v) => Ok(v),
             Err(_) => res,
@@ -1471,7 +1545,11 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn or_else<F, O>(self, op: O) -> Result<T, F>
+    where
+        O: ~const FnOnce(E) -> Result<T, F> + ~const Destruct,
+    {
         match self {
             Ok(t) => Ok(t),
             Err(e) => op(e),
@@ -1498,7 +1576,12 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn unwrap_or(self, default: T) -> T {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn unwrap_or(self, default: T) -> T
+    where
+        T: ~const Destruct,
+        E: ~const Destruct,
+    {
         match self {
             Ok(t) => t,
             Err(_) => default,
@@ -1519,7 +1602,11 @@ impl<T, E> Result<T, E> {
     #[inline]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
+    #[rustc_const_unstable(feature = "const_result_trait_fn", issue = "144211")]
+    pub const fn unwrap_or_else<F>(self, op: F) -> T
+    where
+        F: ~const FnOnce(E) -> T + ~const Destruct,
+    {
         match self {
             Ok(t) => t,
             Err(e) => op(e),
@@ -1544,7 +1631,7 @@ impl<T, E> Result<T, E> {
     ///
     /// ```no_run
     /// let x: Result<u32, &str> = Err("emergency failure");
-    /// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
+    /// unsafe { x.unwrap_unchecked() }; // Undefined behavior!
     /// ```
     #[inline]
     #[track_caller]
@@ -1762,7 +1849,7 @@ impl<T, E> Result<Result<T, E>, E> {
 #[cold]
 #[track_caller]
 fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
-    panic!("{msg}: {error:?}")
+    panic!("{msg}: {error:?}");
 }
 
 // This is a separate function to avoid constructing a `dyn Debug`
@@ -1773,7 +1860,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
 #[inline]
 #[cold]
 #[track_caller]
-fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! {
+const fn unwrap_failed<T>(_msg: &str, _error: &T) -> ! {
     panic!()
 }
 
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 029a7b00ad3..0a9c0c61c95 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -20,6 +20,7 @@
 #![feature(const_eval_select)]
 #![feature(const_ops)]
 #![feature(const_ref_cell)]
+#![feature(const_result_trait_fn)]
 #![feature(const_trait_impl)]
 #![feature(core_float_math)]
 #![feature(core_intrinsics)]
@@ -82,6 +83,7 @@
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
 #![feature(ptr_metadata)]
+#![feature(result_option_map_or_default)]
 #![feature(slice_from_ptr_range)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
diff --git a/library/coretests/tests/result.rs b/library/coretests/tests/result.rs
index 90ec844bc57..39898d5dbb7 100644
--- a/library/coretests/tests/result.rs
+++ b/library/coretests/tests/result.rs
@@ -421,3 +421,86 @@ fn result_try_trait_v2_branch() {
     assert_eq!(Ok::<NonZero<u32>, ()>(one).branch(), Continue(one));
     assert_eq!(Err::<NonZero<u32>, ()>(()).branch(), Break(Err(())));
 }
+
+// helper functions for const contexts
+const fn eq10(x: u8) -> bool {
+    x == 10
+}
+const fn eq20(e: u8) -> bool {
+    e == 20
+}
+const fn double_u16(x: u8) -> u16 {
+    x as u16 * 2
+}
+const fn to_u16(x: u8) -> u16 {
+    x as u16
+}
+const fn err_to_u16_plus1(e: u8) -> u16 {
+    e as u16 + 1
+}
+const fn inc_u8(x: u8) -> u8 {
+    x + 1
+}
+const fn noop_u8_ref(_x: &u8) {}
+const fn add1_result(x: u8) -> Result<u8, u8> {
+    Ok(x + 1)
+}
+const fn add5_result(e: u8) -> Result<u8, u8> {
+    Ok(e + 5)
+}
+const fn plus7_u8(e: u8) -> u8 {
+    e + 7
+}
+
+#[test]
+fn test_const_result() {
+    const {
+        let r_ok: Result<u8, u8> = Ok(10);
+        let r_err: Result<u8, u8> = Err(20);
+        assert!(r_ok.is_ok());
+        assert!(r_err.is_err());
+
+        let ok_and = r_ok.is_ok_and(eq10);
+        let err_and = r_err.is_err_and(eq20);
+        assert!(ok_and);
+        assert!(err_and);
+
+        let opt_ok: Option<u8> = r_ok.ok();
+        let opt_err: Option<u8> = r_err.err();
+        assert!(opt_ok.unwrap() == 10);
+        assert!(opt_err.unwrap() == 20);
+
+        let mapped: Result<u16, u8> = r_ok.map(double_u16);
+        let map_or: u16 = r_ok.map_or(0, to_u16);
+        let map_or_else: u16 = r_err.map_or_else(err_to_u16_plus1, to_u16);
+        let map_or_default: u8 = r_err.map_or_default(inc_u8);
+        assert!(mapped.unwrap_or_default() == 20);
+        assert!(map_or == 10);
+        assert!(map_or_else == 21);
+        assert!(map_or_default == 0);
+
+        let _map_err: Result<u8, u16> = r_err.map_err(to_u16);
+        //FIXME: currently can't unwrap const error
+        // assert!(map_err.unwrap_err() == 20);
+
+        let inspected_ok: Result<u8, u8> = r_ok.inspect(noop_u8_ref);
+        let inspected_err: Result<u8, u8> = r_err.inspect_err(noop_u8_ref);
+        assert!(inspected_ok.is_ok());
+        assert!(inspected_err.is_err());
+
+        let unwrapped_default: u8 = r_err.unwrap_or_default();
+        assert!(unwrapped_default == 0);
+
+        let and_then: Result<u8, u8> = r_ok.and_then(add1_result);
+        let or: Result<u8, u8> = r_err.or(Ok(5));
+        let or_else: Result<u8, u8> = r_err.or_else(add5_result);
+        assert!(and_then.unwrap_or_default() == 11);
+        assert!(or.unwrap_or_default() == 5);
+        assert!(or_else.unwrap_or_default() == 25);
+
+        let u_or: u8 = r_err.unwrap_or(7);
+        let u_or_else: u8 = r_err.unwrap_or_else(plus7_u8);
+        assert!(u_or == 7);
+        assert!(u_or_else == 27);
+    };
+}
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index d9c34d4fa04..055e7f81480 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3259,8 +3259,8 @@ impl Path {
     ///
     /// # Examples
     ///
-    #[cfg_attr(unix, doc = "```no_run")]
-    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// ```rust,no_run
+    /// # #[cfg(unix)] {
     /// use std::path::Path;
     /// use std::os::unix::fs::symlink;
     ///
@@ -3268,6 +3268,7 @@ impl Path {
     /// symlink("/origin_does_not_exist/", link_path).unwrap();
     /// assert_eq!(link_path.is_symlink(), true);
     /// assert_eq!(link_path.exists(), false);
+    /// # }
     /// ```
     ///
     /// # See Also
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index a5c3a6c46a4..b224044cbe0 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -16,6 +16,8 @@ use crate::sync::Once;
 /// A `OnceLock` can be thought of as a safe abstraction over uninitialized data that becomes
 /// initialized once written.
 ///
+/// Unlike [`Mutex`](crate::sync::Mutex), `OnceLock` is never poisoned on panic.
+///
 /// [`OnceCell`]: crate::cell::OnceCell
 /// [`LazyLock<T, F>`]: crate::sync::LazyLock
 /// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index b901a5701a4..d5adc9e29b5 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -2,15 +2,16 @@
 //!
 //! # Poisoning
 //!
-//! All synchronization objects in this module implement a strategy called "poisoning"
-//! where if a thread panics while holding the exclusive access granted by the primitive,
-//! the state of the primitive is set to "poisoned".
-//! This information is then propagated to all other threads
+//! All synchronization objects in this module implement a strategy called
+//! "poisoning" where a primitive becomes poisoned if it recognizes that some
+//! thread has panicked while holding the exclusive access granted by the
+//! primitive. This information is then propagated to all other threads
 //! to signify that the data protected by this primitive is likely tainted
 //! (some invariant is not being upheld).
 //!
-//! The specifics of how this "poisoned" state affects other threads
-//! depend on the primitive. See [#Overview] below.
+//! The specifics of how this "poisoned" state affects other threads and whether
+//! the panics are recognized reliably or on a best-effort basis depend on the
+//! primitive. See [#Overview] below.
 //!
 //! For the alternative implementations that do not employ poisoning,
 //! see [`std::sync::nonpoison`].
@@ -36,14 +37,15 @@
 //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
 //!   most one thread at a time is able to access some data.
 //!
-//!   [`Mutex::lock()`] returns a [`LockResult`],
-//!   providing a way to deal with the poisoned state.
-//!   See [`Mutex`'s documentation](Mutex#poisoning) for more.
+//!   Panicking while holding the lock typically poisons the mutex, but it is
+//!   not guaranteed to detect this condition in all circumstances.
+//!   [`Mutex::lock()`] returns a [`LockResult`], providing a way to deal with
+//!   the poisoned state. See [`Mutex`'s documentation](Mutex#poisoning) for more.
 //!
 //! - [`Once`]: A thread-safe way to run a piece of code only once.
 //!   Mostly useful for implementing one-time global initialization.
 //!
-//!   [`Once`] is poisoned if the piece of code passed to
+//!   [`Once`] is reliably poisoned if the piece of code passed to
 //!   [`Once::call_once()`] or [`Once::call_once_force()`] panics.
 //!   When in poisoned state, subsequent calls to [`Once::call_once()`] will panic too.
 //!   [`Once::call_once_force()`] can be used to clear the poisoned state.
@@ -53,7 +55,7 @@
 //!   writer at a time. In some cases, this can be more efficient than
 //!   a mutex.
 //!
-//!   This implementation, like [`Mutex`], will become poisoned on a panic.
+//!   This implementation, like [`Mutex`], usually becomes poisoned on a panic.
 //!   Note, however, that an `RwLock` may only be poisoned if a panic occurs
 //!   while it is locked exclusively (write mode). If a panic occurs in any reader,
 //!   then the lock will not be poisoned.
diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs
index 64744f18c74..6205c4fa4ca 100644
--- a/library/std/src/sync/poison/mutex.rs
+++ b/library/std/src/sync/poison/mutex.rs
@@ -18,20 +18,69 @@ use crate::sys::sync as sys;
 /// # Poisoning
 ///
 /// The mutexes in this module implement a strategy called "poisoning" where a
-/// mutex is considered poisoned whenever a thread panics while holding the
-/// mutex. Once a mutex is poisoned, all other threads are unable to access the
-/// data by default as it is likely tainted (some invariant is not being
-/// upheld).
+/// mutex becomes poisoned if it recognizes that the thread holding it has
+/// panicked.
 ///
-/// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a
+/// Once a mutex is poisoned, all other threads are unable to access the data by
+/// default as it is likely tainted (some invariant is not being upheld). For a
+/// mutex, this means that the [`lock`] and [`try_lock`] methods return a
 /// [`Result`] which indicates whether a mutex has been poisoned or not. Most
 /// usage of a mutex will simply [`unwrap()`] these results, propagating panics
 /// among threads to ensure that a possibly invalid invariant is not witnessed.
 ///
-/// A poisoned mutex, however, does not prevent all access to the underlying
-/// data. The [`PoisonError`] type has an [`into_inner`] method which will return
-/// the guard that would have otherwise been returned on a successful lock. This
-/// allows access to the data, despite the lock being poisoned.
+/// Poisoning is only advisory: the [`PoisonError`] type has an [`into_inner`]
+/// method which will return the guard that would have otherwise been returned
+/// on a successful lock. This allows access to the data, despite the lock being
+/// poisoned.
+///
+/// In addition, the panic detection is not ideal, so even unpoisoned mutexes
+/// need to be handled with care, since certain panics may have been skipped.
+/// Here is a non-exhaustive list of situations where this might occur:
+///
+/// - If a mutex is locked while a panic is underway, e.g. within a [`Drop`]
+///   implementation or a [panic hook], panicking for the second time while the
+///   lock is held will leave the mutex unpoisoned. Note that while double panic
+///   usually aborts the program, [`catch_unwind`] can prevent this.
+///
+/// - Locking and unlocking the mutex across different panic contexts, e.g. by
+///   storing the guard to a [`Cell`] within [`Drop::drop`] and accessing it
+///   outside, or vice versa, can affect poisoning status in an unexpected way.
+///
+/// - Foreign exceptions do not currently trigger poisoning even in absence of
+///   other panics.
+///
+/// While this rarely happens in realistic code, `unsafe` code cannot rely on
+/// poisoning for soundness, since the behavior of poisoning can depend on
+/// outside context. Here's an example of **incorrect** use of poisoning:
+///
+/// ```rust
+/// use std::sync::Mutex;
+///
+/// struct MutexBox<T> {
+///     data: Mutex<*mut T>,
+/// }
+///
+/// impl<T> MutexBox<T> {
+///     pub fn new(value: T) -> Self {
+///         Self {
+///             data: Mutex::new(Box::into_raw(Box::new(value))),
+///         }
+///     }
+///
+///     pub fn replace_with(&self, f: impl FnOnce(T) -> T) {
+///         let ptr = self.data.lock().expect("poisoned");
+///         // While `f` is running, the data is moved out of `*ptr`. If `f`
+///         // panics, `*ptr` keeps pointing at a dropped value. The intention
+///         // is that this will poison the mutex, so the following calls to
+///         // `replace_with` will panic without reading `*ptr`. But since
+///         // poisoning is not guaranteed to occur if this is run from a panic
+///         // hook, this can lead to use-after-free.
+///         unsafe {
+///             (*ptr).write(f((*ptr).read()));
+///         }
+///     }
+/// }
+/// ```
 ///
 /// [`new`]: Self::new
 /// [`lock`]: Self::lock
@@ -39,6 +88,9 @@ use crate::sys::sync as sys;
 /// [`unwrap()`]: Result::unwrap
 /// [`PoisonError`]: super::PoisonError
 /// [`into_inner`]: super::PoisonError::into_inner
+/// [panic hook]: crate::panic::set_hook
+/// [`catch_unwind`]: crate::panic::catch_unwind
+/// [`Cell`]: crate::cell::Cell
 ///
 /// # Examples
 ///
diff --git a/library/std/src/sync/poison/once.rs b/library/std/src/sync/poison/once.rs
index 103e5195407..faf2913c547 100644
--- a/library/std/src/sync/poison/once.rs
+++ b/library/std/src/sync/poison/once.rs
@@ -136,7 +136,8 @@ impl Once {
     /// it will *poison* this [`Once`] instance, causing all future invocations of
     /// `call_once` to also panic.
     ///
-    /// This is similar to [poisoning with mutexes][poison].
+    /// This is similar to [poisoning with mutexes][poison], but this mechanism
+    /// is guaranteed to never skip panics within `f`.
     ///
     /// [poison]: struct.Mutex.html#poisoning
     #[inline]
@@ -293,6 +294,9 @@ impl Once {
 
     /// Blocks the current thread until initialization has completed, ignoring
     /// poisoning.
+    ///
+    /// If this [`Once`] has been poisoned, this function blocks until it
+    /// becomes completed, unlike [`Once::wait()`], which panics in this case.
     #[stable(feature = "once_wait", since = "1.86.0")]
     pub fn wait_force(&self) {
         if !self.inner.is_completed() {
diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs
index 934a173425a..2c92602bc87 100644
--- a/library/std/src/sync/poison/rwlock.rs
+++ b/library/std/src/sync/poison/rwlock.rs
@@ -46,10 +46,12 @@ use crate::sys::sync as sys;
 ///
 /// # Poisoning
 ///
-/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however,
-/// that an `RwLock` may only be poisoned if a panic occurs while it is locked
-/// exclusively (write mode). If a panic occurs in any reader, then the lock
-/// will not be poisoned.
+/// An `RwLock`, like [`Mutex`], will [usually] become poisoned on a panic. Note,
+/// however, that an `RwLock` may only be poisoned if a panic occurs while it is
+/// locked exclusively (write mode). If a panic occurs in any reader, then the
+/// lock will not be poisoned.
+///
+/// [usually]: super::Mutex#poisoning
 ///
 /// # Examples
 ///
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 119fa4237bc..ffc5dfad459 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -749,6 +749,12 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             SourceType::InTree,
             &[],
         );
+
+        // Used for `compiletest` self-tests to have the path to the *staged* compiler. Getting this
+        // right is important, as `compiletest` is intended to only support one target spec JSON
+        // format, namely that of the staged compiler.
+        cargo.env("TEST_RUSTC", builder.rustc(compiler));
+
         cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
         run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
     }
diff --git a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
index ad570ee4595..04d6469aeaa 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
@@ -11,10 +11,11 @@ jobs:
     if: github.repository == 'rust-lang/rustc-dev-guide'
     uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@main
     with:
+      github-app-id: ${{ vars.APP_CLIENT_ID }}
       zulip-stream-id: 196385
       zulip-bot-email:  "rustc-dev-guide-gha-notif-bot@rust-lang.zulipchat.com"
       pr-base-branch: master
       branch-name: rustc-pull
     secrets:
       zulip-api-token: ${{ secrets.ZULIP_API_TOKEN }}
-      token: ${{ secrets.GITHUB_TOKEN }}
+      github-app-secret: ${{ secrets.APP_PRIVATE_KEY }}
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index b631041b6bf..1ced6098acf 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-2b5e239c6b86cde974b0ef0f8e23754fb08ff3c5
+32e7a4b92b109c24e9822c862a7c74436b50e564
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index e3c0d50fcc7..9ded467d5cd 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -176,6 +176,7 @@
     - [Next-gen trait solving](./solve/trait-solving.md)
         - [Invariants of the type system](./solve/invariants.md)
         - [The solver](./solve/the-solver.md)
+        - [Candidate preference](./solve/candidate-preference.md)
         - [Canonicalization](./solve/canonicalization.md)
         - [Coinduction](./solve/coinduction.md)
         - [Caching](./solve/caching.md)
diff --git a/src/doc/rustc-dev-guide/src/solve/candidate-preference.md b/src/doc/rustc-dev-guide/src/solve/candidate-preference.md
new file mode 100644
index 00000000000..89605294735
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/candidate-preference.md
@@ -0,0 +1,427 @@
+# Candidate preference
+
+There are multiple ways to prove `Trait` and `NormalizesTo` goals. Each such option is called a [`Candidate`]. If there are multiple applicable candidates, we prefer some candidates over others. We store the relevant information in their [`CandidateSource`].
+
+This preference may result in incorrect inference or region constraints and would therefore be unsound during coherence. Because of this, we simply try to merge all candidates in coherence.
+
+## `Trait` goals
+
+Trait goals merge their applicable candidates in [`fn merge_trait_candidates`]. This document provides additional details and references to explain *why* we've got the current preference rules.
+
+### `CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))`
+
+Trivial builtin impls are builtin impls which are known to be always applicable for well-formed types. This means that if one exists, using another candidate should never have fewer constraints. We currently only consider `Sized` - and `MetaSized` - impls to be trivial.
+
+This is necessary to prevent a lifetime error for the following pattern
+
+```rust
+trait Trait<T>: Sized {}
+impl<'a> Trait<u32> for &'a str {}
+impl<'a> Trait<i32> for &'a str {}
+fn is_sized<T: Sized>(_: T) {}
+fn foo<'a, 'b, T>(x: &'b str)
+where
+    &'a str: Trait<T>,
+{
+    // Elaborating the `&'a str: Trait<T>` where-bound results in a
+    // `&'a str: Sized` where-bound. We do not want to prefer this
+    // over the builtin impl. 
+    is_sized(x);
+}
+```
+
+This preference is incorrect in case the builtin impl has a nested goal which relies on a non-param where-clause
+```rust
+struct MyType<'a, T: ?Sized>(&'a (), T);
+fn is_sized<T>() {}
+fn foo<'a, T: ?Sized>()
+where
+    (MyType<'a, T>,): Sized,
+    MyType<'static, T>: Sized,
+{
+    // The where-bound is trivial while the builtin `Sized` impl for tuples
+    // requires proving `MyType<'a, T>: Sized` which can only be proven by
+    // using the where-clause, adding an unnecessary `'static` constraint.
+    is_sized::<(MyType<'a, T>,)>();
+    //~^ ERROR lifetime may not live long enough
+}
+```
+
+### `CandidateSource::ParamEnv`
+
+Once there's at least one *non-global* `ParamEnv` candidate, we prefer *all* `ParamEnv` candidates over other candidate kinds.
+A where-bound is global if it is not higher-ranked and doesn't contain any generic parameters. It may contain `'static`.
+
+We try to apply where-bounds over other candidates as users tends to have the most control over them, so they can most easily
+adjust them in case our candidate preference is incorrect.
+
+#### Preference over `Impl` candidates
+
+This is necessary to avoid region errors in the following example
+
+```rust
+trait Trait<'a> {}
+impl<T> Trait<'static> for T {}
+fn impls_trait<'a, T: Trait<'a>>() {}
+fn foo<'a, T: Trait<'a>>() {
+    impls_trait::<'a, T>();
+}
+```
+
+We also need this as shadowed impls can result in currently ambiguous solver cycles: [trait-system-refactor-initiative#76]. Without preference we'd be forced to fail with ambiguity
+errors if the where-bound results in region constraints to avoid incompleteness.
+```rust
+trait Super {
+    type SuperAssoc;
+}
+
+trait Trait: Super<SuperAssoc = Self::TraitAssoc> {
+    type TraitAssoc;
+}
+
+impl<T, U> Trait for T
+where
+    T: Super<SuperAssoc = U>,
+{
+    type TraitAssoc = U;
+}
+
+fn overflow<T: Trait>() {
+    // We can use the elaborated `Super<SuperAssoc = Self::TraitAssoc>` where-bound
+    // to prove the where-bound of the `T: Trait` implementation. This currently results in
+    // overflow. 
+    let x: <T as Trait>::TraitAssoc;
+}
+```
+
+This preference causes a lot of issues. See [#24066]. Most of the
+issues are caused by prefering where-bounds over impls even if the where-bound guides type inference:
+```rust
+trait Trait<T> {
+    fn call_me(&self, x: T) {}
+}
+impl<T> Trait<u32> for T {}
+impl<T> Trait<i32> for T {}
+fn bug<T: Trait<U>, U>(x: T) {
+    x.call_me(1u32);
+    //~^ ERROR mismatched types
+}
+```
+However, even if we only apply this preference if the where-bound doesn't guide inference, it may still result
+in incorrect lifetime constraints:
+```rust
+trait Trait<'a> {}
+impl<'a> Trait<'a> for &'a str {}
+fn impls_trait<'a, T: Trait<'a>>(_: T) {}
+fn foo<'a, 'b>(x: &'b str)
+where
+    &'a str: Trait<'b>
+{
+    // Need to prove `&'x str: Trait<'b>` with `'b: 'x`.
+    impls_trait::<'b, _>(x);
+    //~^ ERROR lifetime may not live long enough
+}
+```
+
+#### Preference over `AliasBound` candidates
+
+This is necessary to avoid region errors in the following example
+```rust
+trait Bound<'a> {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, 'b, 'c, T>()
+where
+    T: Trait<'a>,
+    for<'hr> T::Assoc: Bound<'hr>,
+{
+    impls_bound::<'b, T::Assoc>();
+    impls_bound::<'c, T::Assoc>();
+}
+```
+It can also result in unnecessary constraints
+```rust
+trait Bound<'a> {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, 'b, T>()
+where
+    T: for<'hr> Trait<'hr>,
+    <T as Trait<'b>>::Assoc: Bound<'a>,
+{
+    // Using the where-bound for `<T as Trait<'a>>::Assoc: Bound<'a>`
+    // unnecessarily equates `<T as Trait<'a>>::Assoc` with the
+    // `<T as Trait<'b>>::Assoc` from the env.
+    impls_bound::<'a, <T as Trait<'a>>::Assoc>();
+    // For a `<T as Trait<'b>>::Assoc: Bound<'b>` the self type of the
+    // where-bound matches, but the arguments of the trait bound don't.
+    impls_bound::<'b, <T as Trait<'b>>::Assoc>();
+}
+```
+
+#### Why no preference for global where-bounds
+
+Global where-bounds are either fully implied by an impl or unsatisfiable. If they are unsatisfiable, we don't really care what happens. If a where-bound is fully implied then using the impl to prove the trait goal cannot result in additional constraints. For trait goals this is only useful for where-bounds which use `'static`:
+
+```rust
+trait A {
+    fn test(&self);
+}
+
+fn foo(x: &dyn A)
+where
+    dyn A + 'static: A, // Using this bound would lead to a lifetime error.
+{
+    x.test();
+}
+```
+More importantly, by using impls here we prevent global where-bounds from shadowing impls when normalizing associated types. There are no known issues from preferring impls over global where-bounds.
+
+#### Why still consider global where-bounds
+
+Given that we just use impls even if there exists a global where-bounds, you may ask why we don't just ignore these global where-bounds entirely: we use them to weaken the inference guidance from non-global where-bounds.
+
+Without a global where-bound, we currently prefer non-global where bounds even though there would be an applicable impl as well. By adding a non-global where-bound, this unnecessary inference guidance is disabled, allowing the following to compile:
+```rust
+fn check<Color>(color: Color)
+where
+    Vec: Into<Color> + Into<f32>,
+{
+    let _: f32 = Vec.into();
+    // Without the global `Vec: Into<f32>`  bound we'd
+    // eagerly use the non-global `Vec: Into<Color>` bound
+    // here, causing this to fail.
+}
+
+struct Vec;
+impl From<Vec> for f32 {
+    fn from(_: Vec) -> Self {
+        loop {}
+    }
+}
+```
+
+### `CandidateSource::AliasBound`
+
+We prefer alias-bound candidates over impls. We currently use this preference to guide type inference, causing the following to compile. I personally don't think this preference is desirable 🤷
+```rust
+pub trait Dyn {
+    type Word: Into<u64>;
+    fn d_tag(&self) -> Self::Word;
+    fn tag32(&self) -> Option<u32> {
+        self.d_tag().into().try_into().ok()
+        // prove `Self::Word: Into<?0>` and then select a method
+        // on `?0`, needs eager inference.
+    }
+}
+```
+```rust
+fn impl_trait() -> impl Into<u32> {
+    0u16
+}
+
+fn main() {
+    // There are two possible types for `x`:
+    // - `u32` by using the "alias bound" of `impl Into<u32>`
+    // - `impl Into<u32>`, i.e. `u16`, by using `impl<T> From<T> for T`
+    //
+    // We infer the type of `x` to be `u32` even though this is not
+    // strictly necessary and can even lead to surprising errors.
+    let x = impl_trait().into();
+    println!("{}", std::mem::size_of_val(&x));
+}
+```
+This preference also avoids ambiguity due to region constraints, I don't know whether people rely on this in practice.
+```rust
+trait Bound<'a> {}
+impl<T> Bound<'static> for T {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, T: Trait<'a>>() {
+    // Should we infer this to `'a` or `'static`.
+    impls_bound::<'_, T::Assoc>();
+}
+```
+
+### `CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_))`
+
+We prefer builtin trait object impls over user-written impls. This is **unsound** and should be remoed in the future. See [#57893](https://github.com/rust-lang/rust/issues/57893) and [#141347](https://github.com/rust-lang/rust/pull/141347) for more details.
+
+## `NormalizesTo` goals
+
+The candidate preference behavior during normalization is implemented in [`fn assemble_and_merge_candidates`].
+
+### Where-bounds shadow impls
+
+Normalization of associated items does not consider impls if the corresponding trait goal has been proven via a `ParamEnv` or `AliasBound` candidate.
+This means that for where-bounds which do not constrain associated types, the associated types remain *rigid*.
+
+This is necessary to avoid unnecessary region constraints from applying impls.
+```rust
+trait Trait<'a> {
+    type Assoc;
+}
+impl Trait<'static> for u32 {
+    type Assoc = u32;
+}
+
+fn bar<'b, T: Trait<'b>>() -> T::Assoc { todo!() }
+fn foo<'a>()
+where
+    u32: Trait<'a>,
+{
+    // Normalizing the return type would use the impl, proving
+    // the `T: Trait` where-bound would use the where-bound, resulting
+    // in different region constraints.
+    bar::<'_, u32>();
+}
+```
+
+### We always consider `AliasBound` candidates
+
+In case the where-bound does not specify the associated item, we consider `AliasBound` candidates instead of treating the alias as rigid, even though the trait goal was proven via a `ParamEnv` candidate.
+
+```rust
+trait Super {
+    type Assoc;
+}
+trait Bound {
+    type Assoc: Super<Assoc = u32>;
+}
+trait Trait: Super {}
+
+// Elaborating the environment results in a `T::Assoc: Super` where-bound.
+// This where-bound must not prevent normalization via the `Super<Assoc = u32>`
+// item bound.
+fn heck<T: Bound<Assoc: Trait>>(x: <T::Assoc as Super>::Assoc) -> u32 {
+    x
+}
+```
+Using such an alias can result in additional region constraints, cc [#133044].
+```rust
+trait Bound<'a> {
+    type Assoc;
+}
+trait Trait {
+    type Assoc: Bound<'static, Assoc = u32>;
+}
+
+fn heck<'a, T: Trait<Assoc: Bound<'a>>>(x: <T::Assoc as Bound<'a>>::Assoc) {
+    // Normalizing the associated type requires `T::Assoc: Bound<'static>` as it
+    // uses the `Bound<'static>` alias-bound instead of keeping the alias rigid.
+    drop(x);
+}
+```
+
+### We prefer `ParamEnv` candidates over `AliasBound`
+
+While we use `AliasBound` candidates if the where-bound does not specify the associated type, in case it does, we prefer the where-bound.
+This is necessary for the following example:
+```rust
+// Make sure we prefer the `I::IntoIterator: Iterator<Item = ()>`
+// where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
+// alias-bound.
+
+trait Iterator {
+    type Item;
+}
+
+trait IntoIterator {
+    type Item;
+    type IntoIter: Iterator<Item = Self::Item>;
+}
+
+fn normalize<I: Iterator<Item = ()>>() {}
+
+fn foo<I>()
+where
+    I: IntoIterator,
+    I::IntoIter: Iterator<Item = ()>,
+{
+    // We need to prefer the `I::IntoIterator: Iterator<Item = ()>`
+    // where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
+    // alias-bound.
+    normalize::<I::IntoIter>();
+}
+```
+
+### We always consider where-bounds
+
+Even if the trait goal was proven via an impl, we still prefer `ParamEnv` candidates, if any exist.
+
+#### We prefer "orphaned" where-bounds
+
+We add "orphaned" `Projection` clauses into the `ParamEnv` when normalizing item bounds of GATs and RPITIT in `fn check_type_bounds`.
+We need to prefer these `ParamEnv` candidates over impls and other where-bounds. 
+```rust
+#![feature(associated_type_defaults)]
+trait Foo {
+    // We should be able to prove that `i32: Baz<Self>` because of
+    // the impl below, which requires that `Self::Bar<()>: Eq<i32>`
+    // which is true, because we assume `for<T> Self::Bar<T> = i32`.
+    type Bar<T>: Baz<Self> = i32;
+}
+trait Baz<T: ?Sized> {}
+impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {}
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+```
+
+I don't fully understand the cases where this preference is actually necessary and haven't been able to exploit this in fun ways yet, but 🤷
+
+#### We prefer global where-bounds over impls
+
+This is necessary for the following to compile. I don't know whether anything relies on it in practice 🤷
+```rust
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+fn foo<T>(x: T) -> <u32 as Id>::This
+where
+    u32: Id<This = T>,
+{
+    x
+}
+```
+This means normalization can result in additional region constraints, cc [#133044].
+```rust
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for &u32 {
+    type Assoc = u32;
+}
+
+fn trait_bound<T: Trait>() {}
+fn normalize<T: Trait<Assoc = u32>>() {}
+
+fn foo<'a>()
+where
+    &'static u32: Trait<Assoc = u32>,
+{
+    trait_bound::<&'a u32>(); // ok, proven via impl
+    normalize::<&'a u32>(); // error, proven via where-bound
+}
+```
+
+[`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/assembly/struct.Candidate.html
+[`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/enum.CandidateSource.html
+[`fn merge_trait_candidates`]: https://github.com/rust-lang/rust/blob/e3ee7f7aea5b45af3b42b5e4713da43876a65ac9/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs#L1342-L1424
+[`fn assemble_and_merge_candidates`]: https://github.com/rust-lang/rust/blob/e3ee7f7aea5b45af3b42b5e4713da43876a65ac9/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs#L920-L1003
+[trait-system-refactor-initiative#76]: https://github.com/rust-lang/trait-system-refactor-initiative/issues/76
+[#24066]: https://github.com/rust-lang/rust/issues/24066
+[#133044]: https://github.com/rust-lang/rust/issues/133044
\ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 89e4d3e9b58..6fff021b0b1 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -52,6 +52,8 @@ not be exhaustive. Directives can generally be found by browsing the
 
 ### Auxiliary builds
 
+See [Building auxiliary crates](compiletest.html#building-auxiliary-crates)
+
 | Directive             | Explanation                                                                                           | Supported test suites | Possible values                               |
 |-----------------------|-------------------------------------------------------------------------------------------------------|-----------------------|-----------------------------------------------|
 | `aux-bin`             | Build a aux binary, made available in `auxiliary/bin` relative to test directory                      | All except `run-make` | Path to auxiliary `.rs` file                  |
@@ -61,8 +63,7 @@ not be exhaustive. Directives can generally be found by browsing the
 | `proc-macro`          | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm].                | All except `run-make` | Path to auxiliary proc-macro `.rs` file       |
 | `build-aux-docs`      | Build docs for auxiliaries as well.  Note that this only works with `aux-build`, not `aux-crate`.     | All except `run-make` | N/A                                           |
 
-[^pm]: please see the Auxiliary proc-macro section in the
-    [compiletest](./compiletest.md) chapter for specifics.
+[^pm]: please see the [Auxiliary proc-macro section](compiletest.html#auxiliary-proc-macro) in the compiletest chapter for specifics.
 
 ### Controlling outcome expectations
 
diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md
index 032da1ca1e8..ae093984223 100644
--- a/src/doc/rustc-dev-guide/src/tests/docker.md
+++ b/src/doc/rustc-dev-guide/src/tests/docker.md
@@ -6,12 +6,12 @@ need to install Docker on a Linux, Windows, or macOS system (typically Linux
 will be much faster than Windows or macOS because the latter use virtual
 machines to emulate a Linux environment).
 
-Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper Python script that tries to replicate what happens on CI as closely as possible:
+Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible:
 
 ```bash
-python3 src/ci/github-actions/ci.py run-local <job-name>
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
 # For example:
-python3 src/ci/github-actions/ci.py run-local dist-x86_64-linux-alt
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux-alt
 ```
 
 If the above script does not work for you, you would like to have more control of the Docker image execution, or you want to understand what exactly happens during Docker job execution, then continue reading below.
@@ -53,15 +53,6 @@ Some additional notes about using the interactive mode:
   containers. With the container name, run `docker exec -it <CONTAINER>
   /bin/bash` where `<CONTAINER>` is the container name like `4ba195e95cef`.
 
-The approach described above is a relatively low-level interface for running the Docker images
-directly. If you want to run a full CI Linux job locally with Docker, in a way that is as close to CI as possible, you can use the following command:
-
-```bash
-cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
-# For example:
-cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux-alt
-```
-
 [Docker]: https://www.docker.com/
 [`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker
 [`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh
diff --git a/src/doc/rustc-dev-guide/triagebot.toml b/src/doc/rustc-dev-guide/triagebot.toml
index b3f4c2d281c..3ac5d57a52b 100644
--- a/src/doc/rustc-dev-guide/triagebot.toml
+++ b/src/doc/rustc-dev-guide/triagebot.toml
@@ -62,9 +62,6 @@ allow-unauthenticated = [
 # Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
 [issue-links]
 
-# Automatically close and reopen PRs made by bots to run CI on them
-[bot-pull-requests]
-
 [behind-upstream]
 days-threshold = 7
 
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index b6ce8551060..e204e1788ba 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -486,6 +486,7 @@ impl fmt::Display for Display<'_> {
                     (sym::debug_assertions, None) => "debug-assertions enabled",
                     (sym::target_os, Some(os)) => match os.as_str() {
                         "android" => "Android",
+                        "cygwin" => "Cygwin",
                         "dragonfly" => "DragonFly BSD",
                         "emscripten" => "Emscripten",
                         "freebsd" => "FreeBSD",
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 89d5acb985b..782311e593b 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -763,13 +763,13 @@ impl Item {
             .iter()
             .filter_map(|attr| match attr {
                 hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) => {
-                    Some(format!("#[link_section = \"{name}\"]"))
+                    Some(format!("#[unsafe(link_section = \"{name}\")]"))
                 }
                 hir::Attribute::Parsed(AttributeKind::NoMangle(..)) => {
-                    Some("#[no_mangle]".to_string())
+                    Some("#[unsafe(no_mangle)]".to_string())
                 }
                 hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) => {
-                    Some(format!("#[export_name = \"{name}\"]"))
+                    Some(format!("#[unsafe(export_name = \"{name}\")]"))
                 }
                 hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) => {
                     Some("#[non_exhaustive]".to_string())
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 5a9aa2a94c8..c9fa3a4837f 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -941,13 +941,21 @@ fn preprocess_link(
     ori_link: &MarkdownLink,
     dox: &str,
 ) -> Option<Result<PreprocessingInfo, PreprocessingError>> {
+    // certain link kinds cannot have their path be urls,
+    // so they should not be ignored, no matter how much they look like urls.
+    // e.g. [https://example.com/] is not a link to example.com.
+    let can_be_url = !matches!(
+        ori_link.kind,
+        LinkType::ShortcutUnknown | LinkType::CollapsedUnknown | LinkType::ReferenceUnknown
+    );
+
     // [] is mostly likely not supposed to be a link
     if ori_link.link.is_empty() {
         return None;
     }
 
     // Bail early for real links.
-    if ori_link.link.contains('/') {
+    if can_be_url && ori_link.link.contains('/') {
         return None;
     }
 
@@ -972,7 +980,7 @@ fn preprocess_link(
         Ok(None) => (None, link, link),
         Err((err_msg, relative_range)) => {
             // Only report error if we would not have ignored this link. See issue #83859.
-            if !should_ignore_link_with_disambiguators(link) {
+            if !(can_be_url && should_ignore_link_with_disambiguators(link)) {
                 let disambiguator_range = match range_between_backticks(&ori_link.range, dox) {
                     MarkdownLinkRange::Destination(no_backticks_range) => {
                         MarkdownLinkRange::Destination(
@@ -989,7 +997,25 @@ fn preprocess_link(
         }
     };
 
-    if should_ignore_link(path_str) {
+    // If there's no backticks, be lenient and revert to the old behavior.
+    // This is to prevent churn by linting on stuff that isn't meant to be a link.
+    // only shortcut links have simple enough syntax that they
+    // are likely to be written accidentally, collapsed and reference links
+    // need 4 metachars, and reference links will not usually use
+    // backticks in the reference name.
+    // therefore, only shortcut syntax gets the lenient behavior.
+    //
+    // here's a truth table for how link kinds that cannot be urls are handled:
+    //
+    // |-------------------------------------------------------|
+    // |              |  is shortcut link  | not shortcut link |
+    // |--------------|--------------------|-------------------|
+    // | has backtick |    never ignore    |    never ignore   |
+    // | no backtick  | ignore if url-like |    never ignore   |
+    // |-------------------------------------------------------|
+    let ignore_urllike =
+        can_be_url || (ori_link.kind == LinkType::ShortcutUnknown && !ori_link.link.contains('`'));
+    if ignore_urllike && should_ignore_link(path_str) {
         return None;
     }
 
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 5682cc57b6f..30d8537b51a 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -203,22 +203,8 @@ impl ConfigBuilder {
         }
 
         args.push("--rustc-path".to_string());
-        // This is a subtle/fragile thing. On rust-lang CI, there is no global
-        // `rustc`, and Cargo doesn't offer a convenient way to get the path to
-        // `rustc`. Fortunately bootstrap sets `RUSTC` for us, which is pointing
-        // to the stage0 compiler.
-        //
-        // Otherwise, if you are running compiletests's tests manually, you
-        // probably don't have `RUSTC` set, in which case this falls back to the
-        // global rustc. If your global rustc is too far out of sync with stage0,
-        // then this may cause confusing errors. Or if for some reason you don't
-        // have rustc in PATH, that would also fail.
-        args.push(std::env::var("RUSTC").unwrap_or_else(|_| {
-            eprintln!(
-                "warning: RUSTC not set, using global rustc (are you not running via bootstrap?)"
-            );
-            "rustc".to_string()
-        }));
+        args.push(std::env::var("TEST_RUSTC").expect("must be configured by bootstrap"));
+
         crate::parse_config(args)
     }
 }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f66d4f98f1f..ba7fcadbc2e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -765,12 +765,6 @@ impl<'test> TestCx<'test> {
         }
 
         if !unexpected.is_empty() || !not_found.is_empty() {
-            self.error(&format!(
-                "{} unexpected diagnostics reported, {} expected diagnostics not reported",
-                unexpected.len(),
-                not_found.len()
-            ));
-
             // Emit locations in a format that is short (relative paths) but "clickable" in editors.
             // Also normalize path separators to `/`.
             let file_name = self
@@ -794,19 +788,20 @@ impl<'test> TestCx<'test> {
                 |suggestions: &mut Vec<_>, e: &Error, kind, line, msg, color, rank| {
                     let mut ret = String::new();
                     if kind {
-                        ret += &format!("{} {}", "with kind".color(color), e.kind);
+                        ret += &format!("{} {}", "with different kind:".color(color), e.kind);
                     }
                     if line {
                         if !ret.is_empty() {
                             ret.push(' ');
                         }
-                        ret += &format!("{} {}", "on line".color(color), line_str(e));
+                        ret += &format!("{} {}", "on different line:".color(color), line_str(e));
                     }
                     if msg {
                         if !ret.is_empty() {
                             ret.push(' ');
                         }
-                        ret += &format!("{} {}", "with message".color(color), e.msg.cyan());
+                        ret +=
+                            &format!("{} {}", "with different message:".color(color), e.msg.cyan());
                     }
                     suggestions.push((ret, rank));
                 };
@@ -829,17 +824,20 @@ impl<'test> TestCx<'test> {
             // - only known line - meh, but suggested
             // - others are not worth suggesting
             if !unexpected.is_empty() {
-                let header = "--- reported in JSON output but not expected in test file ---";
-                println!("{}", header.green());
+                self.error(&format!(
+                    "{} diagnostics reported in JSON output but not expected in test file",
+                    unexpected.len(),
+                ));
                 for error in &unexpected {
                     print_error(error);
                     let mut suggestions = Vec::new();
                     for candidate in &not_found {
+                        let kind_mismatch = candidate.kind != error.kind;
                         let mut push_red_suggestion = |line, msg, rank| {
                             push_suggestion(
                                 &mut suggestions,
                                 candidate,
-                                candidate.kind != error.kind,
+                                kind_mismatch,
                                 line,
                                 msg,
                                 Color::Red,
@@ -851,26 +849,28 @@ impl<'test> TestCx<'test> {
                         } else if candidate.line_num.is_some()
                             && candidate.line_num == error.line_num
                         {
-                            push_red_suggestion(false, true, 1);
+                            push_red_suggestion(false, true, if kind_mismatch { 2 } else { 1 });
                         }
                     }
 
                     show_suggestions(suggestions, "expected", Color::Red);
                 }
-                println!("{}", "---".green());
             }
             if !not_found.is_empty() {
-                let header = "--- expected in test file but not reported in JSON output ---";
-                println!("{}", header.red());
+                self.error(&format!(
+                    "{} diagnostics expected in test file but not reported in JSON output",
+                    not_found.len()
+                ));
                 for error in &not_found {
                     print_error(error);
                     let mut suggestions = Vec::new();
                     for candidate in unexpected.iter().chain(&unimportant) {
+                        let kind_mismatch = candidate.kind != error.kind;
                         let mut push_green_suggestion = |line, msg, rank| {
                             push_suggestion(
                                 &mut suggestions,
                                 candidate,
-                                candidate.kind != error.kind,
+                                kind_mismatch,
                                 line,
                                 msg,
                                 Color::Green,
@@ -882,13 +882,12 @@ impl<'test> TestCx<'test> {
                         } else if candidate.line_num.is_some()
                             && candidate.line_num == error.line_num
                         {
-                            push_green_suggestion(false, true, 1);
+                            push_green_suggestion(false, true, if kind_mismatch { 2 } else { 1 });
                         }
                     }
 
                     show_suggestions(suggestions, "reported", Color::Green);
                 }
-                println!("{}", "---".red());
             }
             panic!(
                 "errors differ from expected\nstatus: {}\ncommand: {}\n",
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
index f5e2f18e68e..2892ff2882a 100644
--- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
@@ -1,17 +1,24 @@
-// Test LVI load hardening on SGX enclave code
+// Test LVI load hardening on SGX enclave code, specifically that `ret` is rewritten.
 
+//@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --crate-type staticlib
-//@ only-x86_64-fortanix-unknown-sgx
+//@ compile-flags: --target x86_64-fortanix-unknown-sgx -Copt-level=0
+//@ needs-llvm-components: x86
+
+#![feature(no_core, lang_items, f16)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 #[no_mangle]
-pub extern "C" fn plus_one(r: &mut u64) {
-    *r = *r + 1;
+pub extern "C" fn dereference(a: &mut u64) -> u64 {
+    // CHECK-LABEL: dereference
+    // CHECK: lfence
+    // CHECK: mov
+    // CHECK: popq [[REGISTER:%[a-z]+]]
+    // CHECK-NEXT: lfence
+    // CHECK-NEXT: jmpq *[[REGISTER]]
+    *a
 }
-
-// CHECK: plus_one
-// CHECK: lfence
-// CHECK-NEXT: incq
-// CHECK: popq [[REGISTER:%[a-z]+]]
-// CHECK-NEXT: lfence
-// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
index f16d68fa255..a0cedc3bc2d 100644
--- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
@@ -1,12 +1,20 @@
 // Test LVI ret hardening on generic rust code
 
+//@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --crate-type staticlib
-//@ only-x86_64-fortanix-unknown-sgx
+//@ compile-flags: --target x86_64-fortanix-unknown-sgx
+//@ needs-llvm-components: x86
+
+#![feature(no_core, lang_items, f16)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 #[no_mangle]
 pub extern "C" fn myret() {}
-// CHECK: myret:
+// CHECK-LABEL: myret:
 // CHECK: popq [[REGISTER:%[a-z]+]]
 // CHECK-NEXT: lfence
 // CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
index a729df8e166..215fb4b804a 100644
--- a/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
+++ b/tests/assembly-llvm/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
@@ -1,13 +1,22 @@
 // Test LVI load hardening on SGX inline assembly code
 
+//@ add-core-stubs
 //@ assembly-output: emit-asm
-//@ compile-flags: --crate-type staticlib
-//@ only-x86_64-fortanix-unknown-sgx
+//@ compile-flags: --target x86_64-fortanix-unknown-sgx
+//@ needs-llvm-components: x86
 
-use std::arch::asm;
+#![feature(no_core, lang_items, f16)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
 
 #[no_mangle]
 pub extern "C" fn get(ptr: *const u64) -> u64 {
+    // CHECK-LABEL: get
+    // CHECK: movq
+    // CHECK-NEXT: lfence
     let value: u64;
     unsafe {
         asm!("mov {}, [{}]",
@@ -17,18 +26,13 @@ pub extern "C" fn get(ptr: *const u64) -> u64 {
     value
 }
 
-// CHECK: get
-// CHECK: movq
-// CHECK-NEXT: lfence
-
 #[no_mangle]
 pub extern "C" fn myret() {
+    // CHECK-LABEL: myret
+    // CHECK: shlq $0, (%rsp)
+    // CHECK-NEXT: lfence
+    // CHECK-NEXT: retq
     unsafe {
         asm!("ret");
     }
 }
-
-// CHECK: myret
-// CHECK: shlq $0, (%rsp)
-// CHECK-NEXT: lfence
-// CHECK-NEXT: retq
diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff
new file mode 100644
index 00000000000..52832e73905
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff
@@ -0,0 +1,15 @@
+- // MIR for `cannot_opt_generic` before RemoveUnneededDrops
++ // MIR for `cannot_opt_generic` after RemoveUnneededDrops
+  
+  fn cannot_opt_generic(_1: T) -> () {
+      let mut _0: ();
+  
+      bb0: {
+          drop(_1) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff
deleted file mode 100644
index 0c73602bec8..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-abort.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `cannot_opt_generic` before RemoveUnneededDrops
-+ // MIR for `cannot_opt_generic` after RemoveUnneededDrops
-  
-  fn cannot_opt_generic(_1: T) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: T;
-      scope 1 (inlined std::mem::drop::<T>) {
-      }
-  
-      bb0: {
-          nop;
-          StorageLive(_3);
-          _3 = move _1;
-          drop(_3) -> [return: bb1, unwind unreachable];
-      }
-  
-      bb1: {
-          StorageDead(_3);
-          nop;
-          nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff
deleted file mode 100644
index 59cce9fbcdd..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.panic-unwind.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-- // MIR for `cannot_opt_generic` before RemoveUnneededDrops
-+ // MIR for `cannot_opt_generic` after RemoveUnneededDrops
-  
-  fn cannot_opt_generic(_1: T) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: T;
-      scope 1 (inlined std::mem::drop::<T>) {
-      }
-  
-      bb0: {
-          nop;
-          StorageLive(_3);
-          _3 = move _1;
-          drop(_3) -> [return: bb2, unwind: bb1];
-      }
-  
-      bb1 (cleanup): {
-          resume;
-      }
-  
-      bb2: {
-          StorageDead(_3);
-          nop;
-          nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff
new file mode 100644
index 00000000000..3d67cada5dd
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff
@@ -0,0 +1,15 @@
+- // MIR for `dont_opt` before RemoveUnneededDrops
++ // MIR for `dont_opt` after RemoveUnneededDrops
+  
+  fn dont_opt(_1: Vec<bool>) -> () {
+      let mut _0: ();
+  
+      bb0: {
+          drop(_1) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff
deleted file mode 100644
index 428b366b5a6..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `dont_opt` before RemoveUnneededDrops
-+ // MIR for `dont_opt` after RemoveUnneededDrops
-  
-  fn dont_opt(_1: Vec<bool>) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: std::vec::Vec<bool>;
-      scope 1 (inlined std::mem::drop::<Vec<bool>>) {
-      }
-  
-      bb0: {
-          nop;
-          StorageLive(_3);
-          _3 = move _1;
-          drop(_3) -> [return: bb1, unwind unreachable];
-      }
-  
-      bb1: {
-          StorageDead(_3);
-          nop;
-          nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff
deleted file mode 100644
index 445c1f82a96..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-unwind.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-- // MIR for `dont_opt` before RemoveUnneededDrops
-+ // MIR for `dont_opt` after RemoveUnneededDrops
-  
-  fn dont_opt(_1: Vec<bool>) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: std::vec::Vec<bool>;
-      scope 1 (inlined std::mem::drop::<Vec<bool>>) {
-      }
-  
-      bb0: {
-          nop;
-          StorageLive(_3);
-          _3 = move _1;
-          drop(_3) -> [return: bb2, unwind: bb1];
-      }
-  
-      bb1 (cleanup): {
-          resume;
-      }
-  
-      bb2: {
-          StorageDead(_3);
-          nop;
-          nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff
new file mode 100644
index 00000000000..cb7e58ca1a1
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.diff
@@ -0,0 +1,15 @@
+- // MIR for `opt` before RemoveUnneededDrops
++ // MIR for `opt` after RemoveUnneededDrops
+  
+  fn opt(_1: bool) -> () {
+      let mut _0: ();
+  
+      bb0: {
+-         drop(_1) -> [return: bb1, unwind unreachable];
+-     }
+- 
+-     bb1: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff
deleted file mode 100644
index 01eb6d4901f..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-abort.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `opt` before RemoveUnneededDrops
-+ // MIR for `opt` after RemoveUnneededDrops
-  
-  fn opt(_1: bool) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: bool;
-      scope 1 (inlined std::mem::drop::<bool>) {
-      }
-  
-      bb0: {
--         nop;
-          StorageLive(_3);
-          _3 = copy _1;
--         drop(_3) -> [return: bb1, unwind unreachable];
--     }
-- 
--     bb1: {
-          StorageDead(_3);
--         nop;
--         nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff
deleted file mode 100644
index c2c3cb76e83..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.opt.RemoveUnneededDrops.panic-unwind.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `opt` before RemoveUnneededDrops
-+ // MIR for `opt` after RemoveUnneededDrops
-  
-  fn opt(_1: bool) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: bool;
-      scope 1 (inlined std::mem::drop::<bool>) {
-      }
-  
-      bb0: {
--         nop;
-          StorageLive(_3);
-          _3 = copy _1;
--         drop(_3) -> [return: bb1, unwind continue];
--     }
-- 
--     bb1: {
-          StorageDead(_3);
--         nop;
--         nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff
new file mode 100644
index 00000000000..1e166eee9fb
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff
@@ -0,0 +1,15 @@
+- // MIR for `opt_generic_copy` before RemoveUnneededDrops
++ // MIR for `opt_generic_copy` after RemoveUnneededDrops
+  
+  fn opt_generic_copy(_1: T) -> () {
+      let mut _0: ();
+  
+      bb0: {
+-         drop(_1) -> [return: bb1, unwind unreachable];
+-     }
+- 
+-     bb1: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff
deleted file mode 100644
index a82ede6196e..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-abort.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `opt_generic_copy` before RemoveUnneededDrops
-+ // MIR for `opt_generic_copy` after RemoveUnneededDrops
-  
-  fn opt_generic_copy(_1: T) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: T;
-      scope 1 (inlined std::mem::drop::<T>) {
-      }
-  
-      bb0: {
--         nop;
-          StorageLive(_3);
-          _3 = copy _1;
--         drop(_3) -> [return: bb1, unwind unreachable];
--     }
-- 
--     bb1: {
-          StorageDead(_3);
--         nop;
--         nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff
deleted file mode 100644
index 6e7c9ead740..00000000000
--- a/tests/mir-opt/remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.panic-unwind.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `opt_generic_copy` before RemoveUnneededDrops
-+ // MIR for `opt_generic_copy` after RemoveUnneededDrops
-  
-  fn opt_generic_copy(_1: T) -> () {
-      debug x => _1;
-      let mut _0: ();
-      let _2: ();
-      let mut _3: T;
-      scope 1 (inlined std::mem::drop::<T>) {
-      }
-  
-      bb0: {
--         nop;
-          StorageLive(_3);
-          _3 = copy _1;
--         drop(_3) -> [return: bb1, unwind continue];
--     }
-- 
--     bb1: {
-          StorageDead(_3);
--         nop;
--         nop;
-          return;
-      }
-  }
-  
diff --git a/tests/mir-opt/remove_unneeded_drops.rs b/tests/mir-opt/remove_unneeded_drops.rs
index cad79e0aa0c..49dc611838e 100644
--- a/tests/mir-opt/remove_unneeded_drops.rs
+++ b/tests/mir-opt/remove_unneeded_drops.rs
@@ -1,28 +1,56 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+//@ test-mir-pass: RemoveUnneededDrops
+
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
 // EMIT_MIR remove_unneeded_drops.opt.RemoveUnneededDrops.diff
+#[custom_mir(dialect = "runtime")]
 fn opt(x: bool) {
-    drop(x);
+    // CHECK-LABEL: fn opt(
+    // CHECK-NOT: drop(
+    mir! {
+        { Drop(x, ReturnTo(bb1), UnwindUnreachable()) }
+        bb1 = { Return() }
+    }
 }
 
 // EMIT_MIR remove_unneeded_drops.dont_opt.RemoveUnneededDrops.diff
+#[custom_mir(dialect = "runtime")]
 fn dont_opt(x: Vec<bool>) {
-    drop(x);
+    // CHECK-LABEL: fn dont_opt(
+    // CHECK: drop(
+    mir! {
+        { Drop(x, ReturnTo(bb1), UnwindUnreachable()) }
+        bb1 = { Return() }
+    }
 }
 
 // EMIT_MIR remove_unneeded_drops.opt_generic_copy.RemoveUnneededDrops.diff
+#[custom_mir(dialect = "runtime")]
 fn opt_generic_copy<T: Copy>(x: T) {
-    drop(x);
+    // CHECK-LABEL: fn opt_generic_copy(
+    // CHECK-NOT: drop(
+    mir! {
+        { Drop(x, ReturnTo(bb1), UnwindUnreachable()) }
+        bb1 = { Return() }
+    }
 }
 
 // EMIT_MIR remove_unneeded_drops.cannot_opt_generic.RemoveUnneededDrops.diff
 // since the pass is not running on monomorphisized code,
 // we can't (but probably should) optimize this
+#[custom_mir(dialect = "runtime")]
 fn cannot_opt_generic<T>(x: T) {
-    drop(x);
+    // CHECK-LABEL: fn cannot_opt_generic(
+    // CHECK: drop(
+    mir! {
+        { Drop(x, ReturnTo(bb1), UnwindUnreachable()) }
+        bb1 = { Return() }
+    }
 }
 
 fn main() {
+    // CHECK-LABEL: fn main(
     opt(true);
     opt_generic_copy(42);
     cannot_opt_generic(42);
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
index e58762aeb6d..89754cdaf90 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs
@@ -13,42 +13,56 @@
 
 //@ only-x86_64-fortanix-unknown-sgx
 
-use run_make_support::{cmd, cwd, llvm_filecheck, llvm_objdump, regex, set_current_dir, target};
+use run_make_support::{
+    cargo, cwd, llvm_filecheck, llvm_objdump, regex, run, set_current_dir, target,
+};
 
 fn main() {
-    let main_dir = cwd();
-    set_current_dir("enclave");
-    // HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
-    // These come from the top-level Rust workspace, that this crate is not a
-    // member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
-    cmd("cargo")
-        .env("RUSTC_BOOTSTRAP", "1")
+    cargo()
         .arg("-v")
-        .arg("run")
+        .arg("build")
         .arg("--target")
         .arg(target())
+        .current_dir("enclave")
+        .env("CC_x86_64_fortanix_unknown_sgx", "clang")
+        .env(
+            "CFLAGS_x86_64_fortanix_unknown_sgx",
+            "-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening",
+        )
+        .env("CXX_x86_64_fortanix_unknown_sgx", "clang++")
+        .env(
+            "CXXFLAGS_x86_64_fortanix_unknown_sgx",
+            "-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening",
+        )
         .run();
-    set_current_dir(&main_dir);
-    // Rust has various ways of adding code to a binary:
+
+    // Rust has several ways of including machine code into a binary:
+    //
     // - Rust code
     // - Inline assembly
     // - Global assembly
     // - C/C++ code compiled as part of Rust crates
-    // For those different kinds, we do have very small code examples that should be
-    // mitigated in some way. Mostly we check that ret instructions should no longer be present.
+    //
+    // For each of those, check that the mitigations are applied. Mostly we check
+    // that ret instructions are no longer present.
+
+    // Check that normal rust code has the right mitigations.
     check("unw_getcontext", "unw_getcontext.checks");
     check("__libunwind_Registers_x86_64_jumpto", "jumpto.checks");
 
     check("std::io::stdio::_print::[[:alnum:]]+", "print.with_frame_pointers.checks");
 
+    // Check that rust global assembly has the right mitigations.
     check("rust_plus_one_global_asm", "rust_plus_one_global_asm.checks");
 
+    // Check that C code compiled using the `cc` crate has the right mitigations.
     check("cc_plus_one_c", "cc_plus_one_c.checks");
     check("cc_plus_one_c_asm", "cc_plus_one_c_asm.checks");
     check("cc_plus_one_cxx", "cc_plus_one_cxx.checks");
     check("cc_plus_one_cxx_asm", "cc_plus_one_cxx_asm.checks");
     check("cc_plus_one_asm", "cc_plus_one_asm.checks");
 
+    // Check that C++ code compiled using the `cc` crate has the right mitigations.
     check("cmake_plus_one_c", "cmake_plus_one_c.checks");
     check("cmake_plus_one_c_asm", "cmake_plus_one_c_asm.checks");
     check("cmake_plus_one_c_global_asm", "cmake_plus_one_c_global_asm.checks");
@@ -71,8 +85,7 @@ fn check(func_re: &str, mut checks: &str) {
         .input("enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave")
         .args(&["--demangle", &format!("--disassemble-symbols={func}")])
         .run()
-        .stdout_utf8();
-    let dump = dump.as_bytes();
+        .stdout();
 
     // Unique case, must succeed at one of two possible tests.
     // This is because frame pointers are optional, and them being enabled requires
diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs
index 1174e16dd53..cb277d529ce 100644
--- a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs
+++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.rs
@@ -2,67 +2,67 @@
 //@ normalize-stderr: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 
 //! [struct@m!()]   //~ WARN: unmatched disambiguator `struct` and suffix `!()`
-//! [struct@m!{}]
+//! [struct@m!{}]   //~ WARN: unmatched disambiguator `struct` and suffix `!{}`
 //! [struct@m![]]
 //! [struct@f()]    //~ WARN: unmatched disambiguator `struct` and suffix `()`
 //! [struct@m!]     //~ WARN: unmatched disambiguator `struct` and suffix `!`
 //!
 //! [enum@m!()]     //~ WARN: unmatched disambiguator `enum` and suffix `!()`
-//! [enum@m!{}]
+//! [enum@m!{}]     //~ WARN: unmatched disambiguator `enum` and suffix `!{}`
 //! [enum@m![]]
 //! [enum@f()]      //~ WARN: unmatched disambiguator `enum` and suffix `()`
 //! [enum@m!]       //~ WARN: unmatched disambiguator `enum` and suffix `!`
 //!
 //! [trait@m!()]    //~ WARN: unmatched disambiguator `trait` and suffix `!()`
-//! [trait@m!{}]
+//! [trait@m!{}]    //~ WARN: unmatched disambiguator `trait` and suffix `!{}`
 //! [trait@m![]]
 //! [trait@f()]     //~ WARN: unmatched disambiguator `trait` and suffix `()`
 //! [trait@m!]      //~ WARN: unmatched disambiguator `trait` and suffix `!`
 //!
 //! [module@m!()]   //~ WARN: unmatched disambiguator `module` and suffix `!()`
-//! [module@m!{}]
+//! [module@m!{}]   //~ WARN: unmatched disambiguator `module` and suffix `!{}`
 //! [module@m![]]
 //! [module@f()]    //~ WARN: unmatched disambiguator `module` and suffix `()`
 //! [module@m!]     //~ WARN: unmatched disambiguator `module` and suffix `!`
 //!
 //! [mod@m!()]      //~ WARN: unmatched disambiguator `mod` and suffix `!()`
-//! [mod@m!{}]
+//! [mod@m!{}]      //~ WARN: unmatched disambiguator `mod` and suffix `!{}`
 //! [mod@m![]]
 //! [mod@f()]       //~ WARN: unmatched disambiguator `mod` and suffix `()`
 //! [mod@m!]        //~ WARN: unmatched disambiguator `mod` and suffix `!`
 //!
 //! [const@m!()]    //~ WARN: unmatched disambiguator `const` and suffix `!()`
-//! [const@m!{}]
+//! [const@m!{}]    //~ WARN: unmatched disambiguator `const` and suffix `!{}`
 //! [const@m![]]
 //! [const@f()]     //~ WARN: incompatible link kind for `f`
 //! [const@m!]      //~ WARN: unmatched disambiguator `const` and suffix `!`
 //!
 //! [constant@m!()]   //~ WARN: unmatched disambiguator `constant` and suffix `!()`
-//! [constant@m!{}]
+//! [constant@m!{}]   //~ WARN:  unmatched disambiguator `constant` and suffix `!{}`
 //! [constant@m![]]
 //! [constant@f()]    //~ WARN: incompatible link kind for `f`
 //! [constant@m!]     //~ WARN: unmatched disambiguator `constant` and suffix `!`
 //!
 //! [static@m!()]   //~ WARN: unmatched disambiguator `static` and suffix `!()`
-//! [static@m!{}]
+//! [static@m!{}]   //~ WARN: unmatched disambiguator `static` and suffix `!{}`
 //! [static@m![]]
 //! [static@f()]    //~ WARN: incompatible link kind for `f`
 //! [static@m!]     //~ WARN: unmatched disambiguator `static` and suffix `!`
 //!
 //! [function@m!()]   //~ WARN: unmatched disambiguator `function` and suffix `!()`
-//! [function@m!{}]
+//! [function@m!{}]   //~ WARN: unmatched disambiguator `function` and suffix `!{}`
 //! [function@m![]]
 //! [function@f()]
 //! [function@m!]     //~ WARN: unmatched disambiguator `function` and suffix `!`
 //!
 //! [fn@m!()]   //~ WARN: unmatched disambiguator `fn` and suffix `!()`
-//! [fn@m!{}]
+//! [fn@m!{}]   //~ WARN: unmatched disambiguator `fn` and suffix `!{}`
 //! [fn@m![]]
 //! [fn@f()]
 //! [fn@m!]     //~ WARN: unmatched disambiguator `fn` and suffix `!`
 //!
 //! [method@m!()]   //~ WARN: unmatched disambiguator `method` and suffix `!()`
-//! [method@m!{}]
+//! [method@m!{}]   //~ WARN: unmatched disambiguator `method` and suffix `!{}`
 //! [method@m![]]
 //! [method@f()]
 //! [method@m!]     //~ WARN: unmatched disambiguator `method` and suffix `!`
@@ -74,13 +74,13 @@
 //! [derive@m!]     //~ WARN: incompatible link kind for `m`
 //!
 //! [type@m!()]   //~ WARN: unmatched disambiguator `type` and suffix `!()`
-//! [type@m!{}]
+//! [type@m!{}]   //~ WARN: unmatched disambiguator `type` and suffix `!{}`
 //! [type@m![]]
 //! [type@f()]    //~ WARN: unmatched disambiguator `type` and suffix `()`
 //! [type@m!]     //~ WARN: unmatched disambiguator `type` and suffix `!`
 //!
 //! [value@m!()]   //~ WARN: unmatched disambiguator `value` and suffix `!()`
-//! [value@m!{}]
+//! [value@m!{}]   //~ WARN: unmatched disambiguator `value` and suffix `!{}`
 //! [value@m![]]
 //! [value@f()]
 //! [value@m!]     //~ WARN: unmatched disambiguator `value` and suffix `!`
@@ -92,13 +92,13 @@
 //! [macro@m!]
 //!
 //! [prim@m!()]   //~ WARN: unmatched disambiguator `prim` and suffix `!()`
-//! [prim@m!{}]
+//! [prim@m!{}]   //~ WARN: unmatched disambiguator `prim` and suffix `!{}`
 //! [prim@m![]]
 //! [prim@f()]    //~ WARN: unmatched disambiguator `prim` and suffix `()`
 //! [prim@m!]     //~ WARN: unmatched disambiguator `prim` and suffix `!`
 //!
 //! [primitive@m!()]   //~ WARN: unmatched disambiguator `primitive` and suffix `!()`
-//! [primitive@m!{}]
+//! [primitive@m!{}]   //~ WARN: unmatched disambiguator `primitive` and suffix `!{}`
 //! [primitive@m![]]
 //! [primitive@f()]    //~ WARN: unmatched disambiguator `primitive` and suffix `()`
 //! [primitive@m!]     //~ WARN: unmatched disambiguator `primitive` and suffix `!`
diff --git a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr
index f4e40a48873..18403385968 100644
--- a/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr
+++ b/tests/rustdoc-ui/disambiguator-endswith-named-suffix.stderr
@@ -7,6 +7,14 @@ LL | //! [struct@m!()]
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
    = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
 
+warning: unmatched disambiguator `struct` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:5:6
+   |
+LL | //! [struct@m!{}]
+   |      ^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `struct` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:7:6
    |
@@ -31,6 +39,14 @@ LL | //! [enum@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `enum` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:11:6
+   |
+LL | //! [enum@m!{}]
+   |      ^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `enum` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:13:6
    |
@@ -55,6 +71,14 @@ LL | //! [trait@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `trait` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:17:6
+   |
+LL | //! [trait@m!{}]
+   |      ^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `trait` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:19:6
    |
@@ -79,6 +103,14 @@ LL | //! [module@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `module` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:23:6
+   |
+LL | //! [module@m!{}]
+   |      ^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `module` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:25:6
    |
@@ -103,6 +135,14 @@ LL | //! [mod@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `mod` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:29:6
+   |
+LL | //! [mod@m!{}]
+   |      ^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `mod` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:31:6
    |
@@ -127,6 +167,14 @@ LL | //! [const@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `const` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:35:6
+   |
+LL | //! [const@m!{}]
+   |      ^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: incompatible link kind for `f`
   --> $DIR/disambiguator-endswith-named-suffix.rs:37:6
    |
@@ -155,6 +203,14 @@ LL | //! [constant@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `constant` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:41:6
+   |
+LL | //! [constant@m!{}]
+   |      ^^^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: incompatible link kind for `f`
   --> $DIR/disambiguator-endswith-named-suffix.rs:43:6
    |
@@ -183,6 +239,14 @@ LL | //! [static@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `static` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:47:6
+   |
+LL | //! [static@m!{}]
+   |      ^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: incompatible link kind for `f`
   --> $DIR/disambiguator-endswith-named-suffix.rs:49:6
    |
@@ -211,6 +275,14 @@ LL | //! [function@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `function` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:53:6
+   |
+LL | //! [function@m!{}]
+   |      ^^^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `function` and suffix `!`
   --> $DIR/disambiguator-endswith-named-suffix.rs:56:6
    |
@@ -227,6 +299,14 @@ LL | //! [fn@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `fn` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:59:6
+   |
+LL | //! [fn@m!{}]
+   |      ^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `fn` and suffix `!`
   --> $DIR/disambiguator-endswith-named-suffix.rs:62:6
    |
@@ -243,6 +323,14 @@ LL | //! [method@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `method` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:65:6
+   |
+LL | //! [method@m!{}]
+   |      ^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `method` and suffix `!`
   --> $DIR/disambiguator-endswith-named-suffix.rs:68:6
    |
@@ -303,6 +391,14 @@ LL | //! [type@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `type` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:77:6
+   |
+LL | //! [type@m!{}]
+   |      ^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `type` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:79:6
    |
@@ -327,6 +423,14 @@ LL | //! [value@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `value` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:83:6
+   |
+LL | //! [value@m!{}]
+   |      ^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `value` and suffix `!`
   --> $DIR/disambiguator-endswith-named-suffix.rs:86:6
    |
@@ -351,6 +455,14 @@ LL | //! [prim@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `prim` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:95:6
+   |
+LL | //! [prim@m!{}]
+   |      ^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `prim` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:97:6
    |
@@ -375,6 +487,14 @@ LL | //! [primitive@m!()]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
+warning: unmatched disambiguator `primitive` and suffix `!{}`
+  --> $DIR/disambiguator-endswith-named-suffix.rs:101:6
+   |
+LL | //! [primitive@m!{}]
+   |      ^^^^^^^^^
+   |
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
 warning: unmatched disambiguator `primitive` and suffix `()`
   --> $DIR/disambiguator-endswith-named-suffix.rs:103:6
    |
@@ -391,5 +511,5 @@ LL | //! [primitive@m!]
    |
    = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
-warning: 46 warnings emitted
+warning: 61 warnings emitted
 
diff --git a/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs b/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs
new file mode 100644
index 00000000000..c24a848d898
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/bad-intra-doc.rs
@@ -0,0 +1,15 @@
+#![no_std]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// regression test for https://github.com/rust-lang/rust/issues/54191
+
+/// this is not a link to [`example.com`] //~ERROR unresolved link
+///
+/// this link [`has spaces in it`].
+///
+/// attempted link to method: [`Foo.bar()`] //~ERROR unresolved link
+///
+/// classic broken intra-doc link: [`Bar`] //~ERROR unresolved link
+///
+/// no backticks, so we let this one slide: [Foo.bar()]
+pub struct Foo;
diff --git a/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr b/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr
new file mode 100644
index 00000000000..9533792b35b
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/bad-intra-doc.stderr
@@ -0,0 +1,31 @@
+error: unresolved link to `example.com`
+  --> $DIR/bad-intra-doc.rs:6:29
+   |
+LL | /// this is not a link to [`example.com`]
+   |                             ^^^^^^^^^^^ no item named `example.com` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+note: the lint level is defined here
+  --> $DIR/bad-intra-doc.rs:2:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unresolved link to `Foo.bar`
+  --> $DIR/bad-intra-doc.rs:10:33
+   |
+LL | /// attempted link to method: [`Foo.bar()`]
+   |                                 ^^^^^^^^^ no item named `Foo.bar` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `Bar`
+  --> $DIR/bad-intra-doc.rs:12:38
+   |
+LL | /// classic broken intra-doc link: [`Bar`]
+   |                                      ^^^ no item named `Bar` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.rs b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
index d2a922b2b62..1c5977b1bc3 100644
--- a/tests/rustdoc-ui/intra-doc/weird-syntax.rs
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.rs
@@ -65,7 +65,7 @@ pub struct XLinkToCloneWithStartSpace;
 /// [x][struct@Clone ] //~ERROR link
 pub struct XLinkToCloneWithEndSpace;
 
-/// [x][Clone\(\)] not URL-shaped enough
+/// [x][Clone\(\)] //~ERROR link
 pub struct XLinkToCloneWithEscapedParens;
 
 /// [x][`Clone`] not URL-shaped enough
diff --git a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
index ad813f0f9b6..7f2fc1fe625 100644
--- a/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
+++ b/tests/rustdoc-ui/intra-doc/weird-syntax.stderr
@@ -123,6 +123,14 @@ LL - /// [x][struct@Clone ]
 LL + /// [x][trait@Clone ]
    |
 
+error: unresolved link to `Clone\(\)`
+  --> $DIR/weird-syntax.rs:68:9
+   |
+LL | /// [x][Clone\(\)]
+   |         ^^^^^^^^^ no item named `Clone\(\)` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
 error: unresolved link to `Clone`
   --> $DIR/weird-syntax.rs:74:9
    |
@@ -299,5 +307,5 @@ LL | /// - [`SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER`]: the
    |
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-error: aborting due to 27 previous errors
+error: aborting due to 28 previous errors
 
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
index 4f4590d45fc..81cd6c73d1c 100644
--- a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
@@ -1,18 +1,24 @@
 //@ check-pass
 
-/// [`…foo`] [`…bar`] [`Err`]
+/// [`…foo`] //~ WARN: unresolved link
+/// [`…bar`] //~ WARN: unresolved link
+/// [`Err`]
 pub struct Broken {}
 
-/// [`…`] [`…`] [`Err`]
+/// [`…`] //~ WARN: unresolved link
+/// [`…`] //~ WARN: unresolved link
+/// [`Err`]
 pub struct Broken2 {}
 
-/// [`…`][…] [`…`][…] [`Err`]
+/// [`…`][…] //~ WARN: unresolved link
+/// [`…`][…] //~ WARN: unresolved link
+/// [`Err`]
 pub struct Broken3 {}
 
 /// […………………………][Broken3]
 pub struct Broken4 {}
 
-/// [Broken3][…………………………]
+/// [Broken3][…………………………] //~ WARN: unresolved link
 pub struct Broken5 {}
 
 pub struct Err;
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr
new file mode 100644
index 00000000000..0a5ff68b908
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.stderr
@@ -0,0 +1,59 @@
+warning: unresolved link to `…foo`
+  --> $DIR/redundant_explicit_links-utf8.rs:3:7
+   |
+LL | /// [`…foo`]
+   |       ^^^^ no item named `…foo` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: unresolved link to `…bar`
+  --> $DIR/redundant_explicit_links-utf8.rs:4:7
+   |
+LL | /// [`…bar`]
+   |       ^^^^ no item named `…bar` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `…`
+  --> $DIR/redundant_explicit_links-utf8.rs:8:7
+   |
+LL | /// [`…`]
+   |       ^ no item named `…` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `…`
+  --> $DIR/redundant_explicit_links-utf8.rs:9:7
+   |
+LL | /// [`…`]
+   |       ^ no item named `…` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `…`
+  --> $DIR/redundant_explicit_links-utf8.rs:13:11
+   |
+LL | /// [`…`][…]
+   |           ^ no item named `…` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `…`
+  --> $DIR/redundant_explicit_links-utf8.rs:14:11
+   |
+LL | /// [`…`][…]
+   |           ^ no item named `…` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `…………………………`
+  --> $DIR/redundant_explicit_links-utf8.rs:21:15
+   |
+LL | /// [Broken3][…………………………]
+   |               ^^^^^^^^^^ no item named `…………………………` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 7 warnings emitted
+
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
index 841533814c3..bf9b81077f3 100644
--- a/tests/rustdoc/attribute-rendering.rs
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -1,7 +1,7 @@
 #![crate_name = "foo"]
 
 //@ has 'foo/fn.f.html'
-//@ has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()'
-#[export_name = "\
-f"]
+//@ has - //*[@'class="rust item-decl"]' '#[unsafe(export_name = "f")] pub fn f()'
+#[unsafe(export_name = "\
+f")]
 pub fn f() {}
diff --git a/tests/rustdoc/attributes-2021-edition.rs b/tests/rustdoc/attributes-2021-edition.rs
new file mode 100644
index 00000000000..b5028d8c852
--- /dev/null
+++ b/tests/rustdoc/attributes-2021-edition.rs
@@ -0,0 +1,14 @@
+//@ edition: 2021
+#![crate_name = "foo"]
+
+//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
+#[no_mangle]
+pub extern "C" fn f() {}
+
+//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]'
+#[export_name = "bar"]
+pub extern "C" fn g() {}
+
+//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]'
+#[link_section = ".text"]
+pub extern "C" fn example() {}
diff --git a/tests/rustdoc/attributes-re-export-2021-edition.rs b/tests/rustdoc/attributes-re-export-2021-edition.rs
new file mode 100644
index 00000000000..04ee6c273dd
--- /dev/null
+++ b/tests/rustdoc/attributes-re-export-2021-edition.rs
@@ -0,0 +1,13 @@
+// Tests that attributes are correctly copied onto a re-exported item.
+//@ edition:2024
+#![crate_name = "re_export"]
+
+//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
+pub use thingymod::thingy as thingy2;
+
+mod thingymod {
+    #[unsafe(no_mangle)]
+    pub fn thingy() {
+
+    }
+}
diff --git a/tests/rustdoc/attributes-re-export.rs b/tests/rustdoc/attributes-re-export.rs
index 458826ea8a3..820276f83c0 100644
--- a/tests/rustdoc/attributes-re-export.rs
+++ b/tests/rustdoc/attributes-re-export.rs
@@ -2,7 +2,7 @@
 //@ edition:2021
 #![crate_name = "re_export"]
 
-//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[no_mangle]'
+//@ has 're_export/fn.thingy2.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
 pub use thingymod::thingy as thingy2;
 
 mod thingymod {
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
index e34468a88b1..34487a89127 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,13 +1,18 @@
+//@ edition: 2024
 #![crate_name = "foo"]
 
-//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]'
-#[no_mangle]
+//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
+#[unsafe(no_mangle)]
 pub extern "C" fn f() {}
 
-//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]'
-#[export_name = "bar"]
+//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]'
+#[unsafe(export_name = "bar")]
 pub extern "C" fn g() {}
 
+//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]'
+#[unsafe(link_section = ".text")]
+pub extern "C" fn example() {}
+
 //@ has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
 #[repr(C, align(8))]
 pub struct Repr;
diff --git a/tests/rustdoc/reexport/reexport-attrs.rs b/tests/rustdoc/reexport/reexport-attrs.rs
index 0ec645841f0..aec0a11c0c6 100644
--- a/tests/rustdoc/reexport/reexport-attrs.rs
+++ b/tests/rustdoc/reexport/reexport-attrs.rs
@@ -4,13 +4,13 @@
 
 extern crate reexports_attrs;
 
-//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[no_mangle]'
+//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
 pub use reexports_attrs::f0;
 
-//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[link_section = ".here"]'
+//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".here")]'
 pub use reexports_attrs::f1;
 
-//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[export_name = "f2export"]'
+//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "f2export")]'
 pub use reexports_attrs::f2;
 
 //@ has 'foo/enum.T0.html' '//pre[@class="rust item-decl"]' '#[repr(u8)]'
diff --git a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs
new file mode 100644
index 00000000000..0c55f13c16c
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.rs
@@ -0,0 +1,10 @@
+#![feature(explicit_tail_calls)]
+#![expect(incomplete_features)]
+
+const _: () = f();
+
+const fn f() {
+    become f(); //~ error: constant evaluation is taking a long time
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr
new file mode 100644
index 00000000000..b5a96114a58
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/infinite-recursion-in-ctfe.stderr
@@ -0,0 +1,17 @@
+error: constant evaluation is taking a long time
+  --> $DIR/infinite-recursion-in-ctfe.rs:7:5
+   |
+LL |     become f();
+   |     ^^^^^^^^^^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/infinite-recursion-in-ctfe.rs:4:1
+   |
+LL | const _: () = f();
+   | ^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs
index 8c194ec50df..ad7b0674478 100644
--- a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs
+++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs
@@ -4,6 +4,7 @@
 
 //@ ignore-emscripten no weak symbol support
 //@ ignore-apple no extern_weak linkage
+//@ ignore-aix no extern_weak linkage
 
 //@ aux-build:lib.rs
 
diff --git a/tests/ui/loop-match/const-continue-to-block.rs b/tests/ui/loop-match/const-continue-to-block.rs
index fd7ebeefeb6..a0f60aaec33 100644
--- a/tests/ui/loop-match/const-continue-to-block.rs
+++ b/tests/ui/loop-match/const-continue-to-block.rs
@@ -24,3 +24,24 @@ fn const_continue_to_block() -> u8 {
         }
     }
 }
+
+fn const_continue_to_shadowed_block() -> u8 {
+    let state = 0;
+    #[loop_match]
+    loop {
+        state = 'blk: {
+            match state {
+                0 => {
+                    #[const_continue]
+                    break 'blk 1;
+                }
+                _ => 'blk: {
+                    //~^ WARN label name `'blk` shadows a label name that is already in scope
+                    #[const_continue]
+                    break 'blk 2;
+                    //~^ ERROR `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
+                }
+            }
+        }
+    }
+}
diff --git a/tests/ui/loop-match/const-continue-to-block.stderr b/tests/ui/loop-match/const-continue-to-block.stderr
index 3a5339a0394..f4e223bcff1 100644
--- a/tests/ui/loop-match/const-continue-to-block.stderr
+++ b/tests/ui/loop-match/const-continue-to-block.stderr
@@ -1,8 +1,23 @@
+warning: label name `'blk` shadows a label name that is already in scope
+  --> $DIR/const-continue-to-block.rs:38:22
+   |
+LL |         state = 'blk: {
+   |                 ---- first declared here
+...
+LL |                 _ => 'blk: {
+   |                      ^^^^ label `'blk` already in scope
+
 error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
   --> $DIR/const-continue-to-block.rs:20:27
    |
 LL |                     break 'b 2;
    |                           ^^
 
-error: aborting due to 1 previous error
+error: `#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
+  --> $DIR/const-continue-to-block.rs:41:27
+   |
+LL |                     break 'blk 2;
+   |                           ^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/loop-match/invalid.rs b/tests/ui/loop-match/invalid.rs
index 0c47b1e0057..08eaf832f56 100644
--- a/tests/ui/loop-match/invalid.rs
+++ b/tests/ui/loop-match/invalid.rs
@@ -142,6 +142,25 @@ fn break_without_value_unit() {
     }
 }
 
+fn break_without_label() {
+    let mut state = State::A;
+    let _ = {
+        #[loop_match]
+        loop {
+            state = 'blk: {
+                match state {
+                    _ => {
+                        #[const_continue]
+                        break State::A;
+                        //~^ ERROR unlabeled `break` inside of a labeled block
+                        //~| ERROR a `#[const_continue]` must break to a label with a value
+                    }
+                }
+            }
+        }
+    };
+}
+
 fn arm_has_guard(cond: bool) {
     let mut state = State::A;
     #[loop_match]
diff --git a/tests/ui/loop-match/invalid.stderr b/tests/ui/loop-match/invalid.stderr
index 70f246caa9c..9e9796a2ea7 100644
--- a/tests/ui/loop-match/invalid.stderr
+++ b/tests/ui/loop-match/invalid.stderr
@@ -9,6 +9,12 @@ help: give the `break` a value of the expected type
 LL |                     break 'blk /* value */;
    |                                +++++++++++
 
+error[E0695]: unlabeled `break` inside of a labeled block
+  --> $DIR/invalid.rs:154:25
+   |
+LL |                         break State::A;
+   |                         ^^^^^^^^^^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label
+
 error: invalid update of the `#[loop_match]` state
   --> $DIR/invalid.rs:18:9
    |
@@ -80,14 +86,20 @@ error: a `#[const_continue]` must break to a label with a value
 LL |                     break 'blk;
    |                     ^^^^^^^^^^
 
+error: a `#[const_continue]` must break to a label with a value
+  --> $DIR/invalid.rs:154:25
+   |
+LL |                         break State::A;
+   |                         ^^^^^^^^^^^^^^
+
 error: match arms that are part of a `#[loop_match]` cannot have guards
-  --> $DIR/invalid.rs:155:29
+  --> $DIR/invalid.rs:174:29
    |
 LL |                 State::B if cond => break 'a,
    |                             ^^^^
 
 error[E0004]: non-exhaustive patterns: `State::B` and `State::C` not covered
-  --> $DIR/invalid.rs:168:19
+  --> $DIR/invalid.rs:187:19
    |
 LL |             match state {
    |                   ^^^^^ patterns `State::B` and `State::C` not covered
@@ -110,12 +122,12 @@ LL ~                 State::B | State::C => todo!(),
    |
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/invalid.rs:185:17
+  --> $DIR/invalid.rs:204:17
    |
 LL |                 4.0..3.0 => {
    |                 ^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: aborting due to 16 previous errors
 
-Some errors have detailed explanations: E0004, E0308, E0579.
+Some errors have detailed explanations: E0004, E0308, E0579, E0695.
 For more information about an error, try `rustc --explain E0004`.