about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml18
-rw-r--r--compiler/rustc_arena/src/lib.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/mod.rs4
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs7
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs28
-rw-r--r--compiler/rustc_lint/messages.ftl13
-rw-r--r--compiler/rustc_lint/src/lints.rs82
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs62
-rw-r--r--compiler/rustc_lint/src/types.rs49
-rw-r--r--compiler/rustc_lint/src/unused.rs94
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs5
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs7
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs92
-rw-r--r--config.example.toml7
-rw-r--r--library/core/benches/slice.rs9
-rw-r--r--library/core/src/macros/mod.rs2
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--library/core/src/slice/iter/macros.rs33
-rw-r--r--library/core/tests/ptr.rs2
-rw-r--r--library/std/src/primitive_docs.rs2
-rw-r--r--src/bootstrap/mk/Makefile.in12
-rw-r--r--src/ci/github-actions/ci.yml20
-rw-r--r--src/doc/rustdoc/src/SUMMARY.md1
-rw-r--r--src/doc/rustdoc/src/write-documentation/re-exports.md172
-rw-r--r--src/doc/rustdoc/src/write-documentation/the-doc-attribute.md8
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed3
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs3
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr48
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs2
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr4
-rw-r--r--src/tools/rustdoc-gui-test/src/main.rs16
-rw-r--r--tests/codegen/slice-iter-fold.rs14
-rw-r--r--tests/codegen/vec-shrink-panik.rs8
-rw-r--r--tests/run-make/panic-abort-eh_frame/Makefile10
-rw-r--r--tests/run-make/panic-abort-eh_frame/foo.rs10
-rw-r--r--tests/rustdoc/issue-109449-doc-hidden-reexports.rs143
-rw-r--r--tests/ui/issues/issue-1460.stderr4
-rw-r--r--tests/ui/lint/issue-112489.rs17
-rw-r--r--tests/ui/lint/type-overflow.stderr28
-rw-r--r--tests/ui/lint/unused/must-use-block-expr.fixed36
-rw-r--r--tests/ui/lint/unused/must-use-block-expr.rs36
-rw-r--r--tests/ui/lint/unused/must-use-block-expr.stderr51
-rw-r--r--tests/ui/match/issue-112438.rs11
-rw-r--r--tests/ui/resolve/issue-112472-multi-generics-suggestion.fixed31
-rw-r--r--tests/ui/resolve/issue-112472-multi-generics-suggestion.rs31
-rw-r--r--tests/ui/resolve/issue-112472-multi-generics-suggestion.stderr25
50 files changed, 1075 insertions, 201 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 210ec72a11e..f87aecb6876 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -383,25 +383,15 @@ jobs:
               DIST_REQUIRE_ALL_TOOLS: 1
               JEMALLOC_SYS_WITH_LG_PAGE: 14
             os: macos-latest
-          - name: x86_64-msvc-1
+          - name: x86_64-msvc
             env:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
-              SCRIPT: make ci-subset-1
+              SCRIPT: make ci-msvc
             os: windows-2019-8core-32gb
-          - name: x86_64-msvc-2
-            env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
-              SCRIPT: make ci-subset-2
-            os: windows-2019-8core-32gb
-          - name: i686-msvc-1
-            env:
-              RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc"
-              SCRIPT: make ci-subset-1
-            os: windows-2019-8core-32gb
-          - name: i686-msvc-2
+          - name: i686-msvc
             env:
               RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc"
-              SCRIPT: make ci-subset-2
+              SCRIPT: make ci-msvc
             os: windows-2019-8core-32gb
           - name: x86_64-msvc-cargo
             env:
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 6e15f06a76d..ba47ebd68cb 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -67,7 +67,7 @@ struct ArenaChunk<T = u8> {
 
 unsafe impl<#[may_dangle] T> Drop for ArenaChunk<T> {
     fn drop(&mut self) {
-        unsafe { Box::from_raw(self.storage.as_mut()) };
+        unsafe { drop(Box::from_raw(self.storage.as_mut())) }
     }
 }
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index ac9e7d06c4e..83b7e13905a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -32,6 +32,10 @@ pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String {
     State::new().bounds_to_string(bounds)
 }
 
+pub fn where_bound_predicate_to_string(where_bound_predicate: &ast::WhereBoundPredicate) -> String {
+    State::new().where_bound_predicate_to_string(where_bound_predicate)
+}
+
 pub fn pat_to_string(pat: &ast::Pat) -> String {
     State::new().pat_to_string(pat)
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 3f80728a260..59239b49edd 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -824,6 +824,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         Self::to_string(|s| s.print_type_bounds(bounds))
     }
 
+    fn where_bound_predicate_to_string(
+        &self,
+        where_bound_predicate: &ast::WhereBoundPredicate,
+    ) -> String {
+        Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
+    }
+
     fn pat_to_string(&self, pat: &ast::Pat) -> String {
         Self::to_string(|s| s.print_pat(pat))
     }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index c465f8c948a..5c01b7ea70a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -623,19 +623,8 @@ impl<'a> State<'a> {
 
     pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
         match predicate {
-            ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
-                bound_generic_params,
-                bounded_ty,
-                bounds,
-                ..
-            }) => {
-                self.print_formal_generic_params(bound_generic_params);
-                self.print_type(bounded_ty);
-                self.word(":");
-                if !bounds.is_empty() {
-                    self.nbsp();
-                    self.print_type_bounds(bounds);
-                }
+            ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
+                self.print_where_bound_predicate(where_bound_predicate);
             }
             ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
                 lifetime,
@@ -658,6 +647,19 @@ impl<'a> State<'a> {
         }
     }
 
+    pub fn print_where_bound_predicate(
+        &mut self,
+        where_bound_predicate: &ast::WhereBoundPredicate,
+    ) {
+        self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
+        self.print_type(&where_bound_predicate.bounded_ty);
+        self.word(":");
+        if !where_bound_predicate.bounds.is_empty() {
+            self.nbsp();
+            self.print_type_bounds(&where_bound_predicate.bounds);
+        }
+    }
+
     fn print_use_tree(&mut self, tree: &ast::UseTree) {
         match &tree.kind {
             ast::UseTreeKind::Simple(rename) => {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 5e13ee7b8a4..34b7e09576a 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -425,6 +425,7 @@ lint_overflowing_bin_hex = literal out of range for `{$ty}`
     .negative_becomes_note = and the value `-{$lit}` will become `{$actually}{$ty}`
     .positive_note = the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`
     .suggestion = consider using the type `{$suggestion_ty}` instead
+    .sign_bit_suggestion = to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`
     .help = consider using the type `{$suggestion_ty}` instead
 
 lint_overflowing_int = literal out of range for `{$ty}`
@@ -478,13 +479,11 @@ lint_requested_level = requested on the command line with `{$level} {$lint_name}
 lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
     .label = target type is set here
 
-lint_suspicious_double_ref_op =
-    using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op ->
-        *[should_not_happen] [{$op}]
-        [deref] dereferencing
-        [borrow] borrowing
-        [clone] cloning
-    } the inner type
+lint_suspicious_double_ref_clone =
+    using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type
+
+lint_suspicious_double_ref_deref =
+    using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
 lint_trivial_untranslatable_diag = diagnostic with static strings only
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index e990c771bdf..49597516b36 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1231,11 +1231,15 @@ pub struct NoopMethodCallDiag<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_suspicious_double_ref_op)]
-pub struct SuspiciousDoubleRefDiag<'a> {
-    pub call: Symbol,
+#[diag(lint_suspicious_double_ref_deref)]
+pub struct SuspiciousDoubleRefDerefDiag<'a> {
+    pub ty: Ty<'a>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_suspicious_double_ref_clone)]
+pub struct SuspiciousDoubleRefCloneDiag<'a> {
     pub ty: Ty<'a>,
-    pub op: &'static str,
 }
 
 // pass_by_value.rs
@@ -1342,6 +1346,8 @@ pub struct OverflowingBinHex<'a> {
     pub sign: OverflowingBinHexSign,
     #[subdiagnostic]
     pub sub: Option<OverflowingBinHexSub<'a>>,
+    #[subdiagnostic]
+    pub sign_bit_sub: Option<OverflowingBinHexSignBitSub<'a>>,
 }
 
 pub enum OverflowingBinHexSign {
@@ -1386,6 +1392,21 @@ pub enum OverflowingBinHexSub<'a> {
     Help { suggestion_ty: &'a str },
 }
 
+#[derive(Subdiagnostic)]
+#[suggestion(
+    lint_sign_bit_suggestion,
+    code = "{lit_no_suffix}{uint_ty} as {int_ty}",
+    applicability = "maybe-incorrect"
+)]
+pub struct OverflowingBinHexSignBitSub<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub lit_no_suffix: &'a str,
+    pub negative_val: String,
+    pub uint_ty: &'a str,
+    pub int_ty: &'a str,
+}
+
 #[derive(LintDiagnostic)]
 #[diag(lint_overflowing_int)]
 #[note]
@@ -1534,8 +1555,29 @@ pub struct UnusedOp<'a> {
     pub op: &'a str,
     #[label]
     pub label: Span,
-    #[suggestion(style = "verbose", code = "let _ = ", applicability = "maybe-incorrect")]
-    pub suggestion: Span,
+    #[subdiagnostic]
+    pub suggestion: UnusedOpSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedOpSuggestion {
+    #[suggestion(
+        lint_suggestion,
+        style = "verbose",
+        code = "let _ = ",
+        applicability = "maybe-incorrect"
+    )]
+    NormalExpr {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
+    BlockTailExpr {
+        #[suggestion_part(code = "let _ = ")]
+        before_span: Span,
+        #[suggestion_part(code = ";")]
+        after_span: Span,
+    },
 }
 
 #[derive(LintDiagnostic)]
@@ -1578,15 +1620,25 @@ pub struct UnusedDef<'a, 'b> {
 }
 
 #[derive(Subdiagnostic)]
-#[suggestion(
-    lint_suggestion,
-    style = "verbose",
-    code = "let _ = ",
-    applicability = "maybe-incorrect"
-)]
-pub struct UnusedDefSuggestion {
-    #[primary_span]
-    pub span: Span,
+
+pub enum UnusedDefSuggestion {
+    #[suggestion(
+        lint_suggestion,
+        style = "verbose",
+        code = "let _ = ",
+        applicability = "maybe-incorrect"
+    )]
+    NormalExpr {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
+    BlockTailExpr {
+        #[suggestion_part(code = "let _ = ")]
+        before_span: Span,
+        #[suggestion_part(code = ";")]
+        after_span: Span,
+    },
 }
 
 // Needed because of def_path_str
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index d054966459d..d56c35bb677 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -1,5 +1,7 @@
 use crate::context::LintContext;
-use crate::lints::{NoopMethodCallDiag, SuspiciousDoubleRefDiag};
+use crate::lints::{
+    NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag,
+};
 use crate::LateContext;
 use crate::LateLintPass;
 use rustc_hir::def::DefKind;
@@ -76,22 +78,22 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
 
         // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
         // traits and ignore any other method call.
-        let did = match cx.typeck_results().type_dependent_def(expr.hir_id) {
-            // Verify we are dealing with a method/associated function.
-            Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) {
-                // Check that we're dealing with a trait method for one of the traits we care about.
-                Some(trait_id)
-                    if matches!(
-                        cx.tcx.get_diagnostic_name(trait_id),
-                        Some(sym::Borrow | sym::Clone | sym::Deref)
-                    ) =>
-                {
-                    did
-                }
-                _ => return,
-            },
-            _ => return,
+
+        let Some((DefKind::AssocFn, did)) =
+            cx.typeck_results().type_dependent_def(expr.hir_id)
+        else {
+            return;
+        };
+
+        let Some(trait_id) = cx.tcx.trait_of_item(did) else { return };
+
+        if !matches!(
+            cx.tcx.get_diagnostic_name(trait_id),
+            Some(sym::Borrow | sym::Clone | sym::Deref)
+        ) {
+            return;
         };
+
         let substs = cx
             .tcx
             .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_substs(expr.hir_id));
@@ -102,13 +104,6 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
         // (Re)check that it implements the noop diagnostic.
         let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return };
 
-        let op = match name {
-            sym::noop_method_borrow => "borrow",
-            sym::noop_method_clone => "clone",
-            sym::noop_method_deref => "deref",
-            _ => return,
-        };
-
         let receiver_ty = cx.typeck_results().expr_ty(receiver);
         let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
         let arg_adjustments = cx.typeck_results().expr_adjustments(receiver);
@@ -129,11 +124,22 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
                 NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span },
             );
         } else {
-            cx.emit_spanned_lint(
-                SUSPICIOUS_DOUBLE_REF_OP,
-                span,
-                SuspiciousDoubleRefDiag { call: call.ident.name, ty: expr_ty, op },
-            )
+            match name {
+                // If `type_of(x) == T` and `x.borrow()` is used to get `&T`,
+                // then that should be allowed
+                sym::noop_method_borrow => return,
+                sym::noop_method_clone => cx.emit_spanned_lint(
+                    SUSPICIOUS_DOUBLE_REF_OP,
+                    span,
+                    SuspiciousDoubleRefCloneDiag { ty: expr_ty },
+                ),
+                sym::noop_method_deref => cx.emit_spanned_lint(
+                    SUSPICIOUS_DOUBLE_REF_OP,
+                    span,
+                    SuspiciousDoubleRefDerefDiag { ty: expr_ty },
+                ),
+                _ => return,
+            }
         }
     }
 }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 264a59c5585..ec9e7c7fdae 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -3,9 +3,10 @@ use crate::{
     lints::{
         AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
         InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
-        OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSub,
-        OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
-        RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
+        OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
+        OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
+        OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
+        VariantSizeDifferencesDiag,
     },
 };
 use crate::{LateContext, LateLintPass, LintContext};
@@ -297,10 +298,50 @@ fn report_bin_hex_error(
             }
         },
     );
+    let sign_bit_sub = (!negative)
+        .then(|| {
+            let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
+                return None;
+            };
+
+            let Some(bit_width) = int_ty.bit_width() else {
+                return None; // isize case
+            };
+
+            // Skip if sign bit is not set
+            if (val & (1 << (bit_width - 1))) == 0 {
+                return None;
+            }
+
+            let lit_no_suffix =
+                if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
+                    repr_str.split_at(pos).0
+                } else {
+                    &repr_str
+                };
+
+            Some(OverflowingBinHexSignBitSub {
+                span: expr.span,
+                lit_no_suffix,
+                negative_val: actually.clone(),
+                int_ty: int_ty.name_str(),
+                uint_ty: int_ty.to_unsigned().name_str(),
+            })
+        })
+        .flatten();
+
     cx.emit_spanned_lint(
         OVERFLOWING_LITERALS,
         expr.span,
-        OverflowingBinHex { ty: t, lit: repr_str.clone(), dec: val, actually, sign, sub },
+        OverflowingBinHex {
+            ty: t,
+            lit: repr_str.clone(),
+            dec: val,
+            actually,
+            sign,
+            sub,
+            sign_bit_sub,
+        },
     )
 }
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 04df23c736b..9861610612f 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,7 +1,8 @@
 use crate::lints::{
     PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
     UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
-    UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
+    UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
+    UnusedResult,
 };
 use crate::Lint;
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -93,7 +94,15 @@ declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'tcx> LateLintPass<'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
-        let hir::StmtKind::Semi(expr) = s.kind else { return; };
+        let hir::StmtKind::Semi(mut expr) = s.kind else { return; };
+
+        let mut expr_is_from_block = false;
+        while let hir::ExprKind::Block(blk, ..) = expr.kind
+            && let hir::Block { expr: Some(e), .. } = blk
+        {
+            expr = e;
+            expr_is_from_block = true;
+        }
 
         if let hir::ExprKind::Ret(..) = expr.kind {
             return;
@@ -113,6 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 expr.span,
                 "output of future returned by ",
                 "",
+                expr_is_from_block,
             )
         {
             // We have a bare `foo().await;` on an opaque type from an async function that was
@@ -125,13 +135,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
         let must_use_result = is_ty_must_use(cx, ty, &expr, expr.span);
         let type_lint_emitted_or_suppressed = match must_use_result {
             Some(path) => {
-                emit_must_use_untranslated(cx, &path, "", "", 1, false);
+                emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block);
                 true
             }
             None => false,
         };
 
-        let fn_warned = check_fn_must_use(cx, expr);
+        let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block);
 
         if !fn_warned && type_lint_emitted_or_suppressed {
             // We don't warn about unused unit or uninhabited types.
@@ -176,7 +186,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 UnusedOp {
                     op: must_use_op,
                     label: expr.span,
-                    suggestion: expr.span.shrink_to_lo(),
+                    suggestion: if expr_is_from_block {
+                        UnusedOpSuggestion::BlockTailExpr {
+                            before_span: expr.span.shrink_to_lo(),
+                            after_span: expr.span.shrink_to_hi(),
+                        }
+                    } else {
+                        UnusedOpSuggestion::NormalExpr { span: expr.span.shrink_to_lo() }
+                    },
                 },
             );
             op_warned = true;
@@ -186,7 +203,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
         }
 
-        fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+        fn check_fn_must_use(
+            cx: &LateContext<'_>,
+            expr: &hir::Expr<'_>,
+            expr_is_from_block: bool,
+        ) -> bool {
             let maybe_def_id = match expr.kind {
                 hir::ExprKind::Call(ref callee, _) => {
                     match callee.kind {
@@ -207,7 +228,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 _ => None,
             };
             if let Some(def_id) = maybe_def_id {
-                check_must_use_def(cx, def_id, expr.span, "return value of ", "")
+                check_must_use_def(
+                    cx,
+                    def_id,
+                    expr.span,
+                    "return value of ",
+                    "",
+                    expr_is_from_block,
+                )
             } else {
                 false
             }
@@ -350,6 +378,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             span: Span,
             descr_pre_path: &str,
             descr_post_path: &str,
+            expr_is_from_block: bool,
         ) -> bool {
             is_def_must_use(cx, def_id, span)
                 .map(|must_use_path| {
@@ -360,6 +389,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         descr_post_path,
                         1,
                         false,
+                        expr_is_from_block,
                     )
                 })
                 .is_some()
@@ -373,6 +403,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             descr_post: &str,
             plural_len: usize,
             is_inner: bool,
+            expr_is_from_block: bool,
         ) {
             let plural_suffix = pluralize!(plural_len);
 
@@ -380,21 +411,51 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 MustUsePath::Suppressed => {}
                 MustUsePath::Boxed(path) => {
                     let descr_pre = &format!("{}boxed ", descr_pre);
-                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
+                    emit_must_use_untranslated(
+                        cx,
+                        path,
+                        descr_pre,
+                        descr_post,
+                        plural_len,
+                        true,
+                        expr_is_from_block,
+                    );
                 }
                 MustUsePath::Opaque(path) => {
                     let descr_pre = &format!("{}implementer{} of ", descr_pre, plural_suffix);
-                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
+                    emit_must_use_untranslated(
+                        cx,
+                        path,
+                        descr_pre,
+                        descr_post,
+                        plural_len,
+                        true,
+                        expr_is_from_block,
+                    );
                 }
                 MustUsePath::TraitObject(path) => {
                     let descr_post = &format!(" trait object{}{}", plural_suffix, descr_post);
-                    emit_must_use_untranslated(cx, path, descr_pre, descr_post, plural_len, true);
+                    emit_must_use_untranslated(
+                        cx,
+                        path,
+                        descr_pre,
+                        descr_post,
+                        plural_len,
+                        true,
+                        expr_is_from_block,
+                    );
                 }
                 MustUsePath::TupleElement(elems) => {
                     for (index, path) in elems {
                         let descr_post = &format!(" in tuple element {}", index);
                         emit_must_use_untranslated(
-                            cx, path, descr_pre, descr_post, plural_len, true,
+                            cx,
+                            path,
+                            descr_pre,
+                            descr_post,
+                            plural_len,
+                            true,
+                            expr_is_from_block,
                         );
                     }
                 }
@@ -407,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                         descr_post,
                         plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)),
                         true,
+                        expr_is_from_block,
                     );
                 }
                 MustUsePath::Closure(span) => {
@@ -433,8 +495,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                             cx,
                             def_id: *def_id,
                             note: *reason,
-                            suggestion: (!is_inner)
-                                .then_some(UnusedDefSuggestion { span: span.shrink_to_lo() }),
+                            suggestion: (!is_inner).then_some(if expr_is_from_block {
+                                UnusedDefSuggestion::BlockTailExpr {
+                                    before_span: span.shrink_to_lo(),
+                                    after_span: span.shrink_to_hi(),
+                                }
+                            } else {
+                                UnusedDefSuggestion::NormalExpr { span: span.shrink_to_lo() }
+                            }),
                         },
                     );
                 }
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index f53dc8cb0ec..ae32a54be3d 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -95,7 +95,10 @@ impl<'tcx> TyCtxt<'tcx> {
                     // used generic parameters is a bug of evaluation, so checking for it
                     // here does feel somewhat sensible.
                     if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
-                        assert!(matches!(self.def_kind(ct.def), DefKind::AnonConst));
+                        assert!(matches!(
+                            self.def_kind(ct.def),
+                            DefKind::InlineConst | DefKind::AnonConst
+                        ));
                         let mir_body = self.mir_for_ctfe(ct.def);
                         if mir_body.is_polymorphic {
                             let Some(local_def_id) = ct.def.as_local() else { return };
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 1fe8ea07892..ef64f70fdf3 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -9,6 +9,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::{Ty, TyCtxt, TypeAndMut};
 use rustc_session::Session;
+use rustc_target::spec::PanicStrategy;
 
 pub struct CheckAlignment;
 
@@ -236,7 +237,11 @@ fn insert_alignment_check<'tcx>(
                 required: Operand::Copy(alignment),
                 found: Operand::Copy(addr),
             }),
-            unwind: UnwindAction::Terminate,
+            unwind: if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
+                UnwindAction::Terminate
+            } else {
+                UnwindAction::Unreachable
+            },
         },
     });
 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index e4b01ef2b17..7284b33f09d 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -10,7 +10,7 @@ use rustc_ast::{
     self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
     MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
 };
-use rustc_ast_pretty::pprust::path_segment_to_string;
+use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
     pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -1050,7 +1050,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             };
 
         // Confirm that the target is an associated type.
-        let (ty, position, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
+        let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
             // use this to verify that ident is a type param.
             let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
                 return false;
@@ -1079,7 +1079,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 return false;
             }
             if let (
-                [ast::PathSegment { ident: constrain_ident, args: None, .. }],
+                [ast::PathSegment { args: None, .. }],
                 [ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
             ) = (&type_param_path.segments[..], &bounds[..])
             {
@@ -1087,29 +1087,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                     &poly_trait_ref.trait_ref.path.segments[..]
                 {
                     if ident.span == span {
+                        let Some(new_where_bound_predicate) = mk_where_bound_predicate(path, poly_trait_ref, ty) else { return false; };
                         err.span_suggestion_verbose(
                             *where_span,
                             format!("constrain the associated type to `{}`", ident),
-                            format!(
-                                "{}: {}<{} = {}>",
-                                self.r
-                                    .tcx
-                                    .sess
-                                    .source_map()
-                                    .span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
-                                    .unwrap_or_else(|_| constrain_ident.to_string()),
-                                path.segments[..position]
-                                    .iter()
-                                    .map(|segment| path_segment_to_string(segment))
-                                    .collect::<Vec<_>>()
-                                    .join("::"),
-                                path.segments[position..]
-                                    .iter()
-                                    .map(|segment| path_segment_to_string(segment))
-                                    .collect::<Vec<_>>()
-                                    .join("::"),
-                                ident,
-                            ),
+                            where_bound_predicate_to_string(&new_where_bound_predicate),
                             Applicability::MaybeIncorrect,
                         );
                     }
@@ -2605,6 +2587,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     }
 }
 
+fn mk_where_bound_predicate(
+    path: &Path,
+    poly_trait_ref: &ast::PolyTraitRef,
+    ty: &ast::Ty,
+) -> Option<ast::WhereBoundPredicate> {
+    use rustc_span::DUMMY_SP;
+    let modified_segments = {
+        let mut segments = path.segments.clone();
+        let [preceding @ .., second_last, last] = segments.as_mut_slice() else { return None; };
+        let mut segments = ThinVec::from(preceding);
+
+        let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint {
+            id: DUMMY_NODE_ID,
+            ident: last.ident,
+            gen_args: None,
+            kind: ast::AssocConstraintKind::Equality {
+                term: ast::Term::Ty(ast::ptr::P(ast::Ty {
+                    kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
+                    id: DUMMY_NODE_ID,
+                    span: DUMMY_SP,
+                    tokens: None,
+                })),
+            },
+            span: DUMMY_SP,
+        });
+
+        match second_last.args.as_deref_mut() {
+            Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
+                args.push(added_constraint);
+            }
+            Some(_) => return None,
+            None => {
+                second_last.args =
+                    Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
+                        args: ThinVec::from([added_constraint]),
+                        span: DUMMY_SP,
+                    })));
+            }
+        }
+
+        segments.push(second_last.clone());
+        segments
+    };
+
+    let new_where_bound_predicate = ast::WhereBoundPredicate {
+        span: DUMMY_SP,
+        bound_generic_params: ThinVec::new(),
+        bounded_ty: ast::ptr::P(ty.clone()),
+        bounds: vec![ast::GenericBound::Trait(
+            ast::PolyTraitRef {
+                bound_generic_params: ThinVec::new(),
+                trait_ref: ast::TraitRef {
+                    path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
+                    ref_id: DUMMY_NODE_ID,
+                },
+                span: DUMMY_SP,
+            },
+            ast::TraitBoundModifier::None,
+        )],
+    };
+
+    Some(new_where_bound_predicate)
+}
+
 /// Report lifetime/lifetime shadowing as an error.
 pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
     let mut err = struct_span_err!(
diff --git a/config.example.toml b/config.example.toml
index d0eaa9fd7ff..0c65b25fe13 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -250,6 +250,13 @@ changelog-seen = 2
 # target when running tests, otherwise this can be omitted.
 #nodejs = "node"
 
+# The npm executable to use. Note that this is used for rustdoc-gui tests,
+# otherwise this can be omitted.
+#
+# Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or
+# error will be emitted.
+#npm = "npm"
+
 # Python interpreter to use for various tasks throughout the build, notably
 # rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
 #
diff --git a/library/core/benches/slice.rs b/library/core/benches/slice.rs
index 9b86a0ca97c..3bfb35e684e 100644
--- a/library/core/benches/slice.rs
+++ b/library/core/benches/slice.rs
@@ -1,3 +1,4 @@
+use core::ptr::NonNull;
 use test::black_box;
 use test::Bencher;
 
@@ -162,3 +163,11 @@ fn fill_byte_sized(b: &mut Bencher) {
         black_box(slice.fill(black_box(NewType(42))));
     });
 }
+
+// Tests the ability of the compiler to recognize that only the last slice item is needed
+// based on issue #106288
+#[bench]
+fn fold_to_last(b: &mut Bencher) {
+    let slice: &[i32] = &[0; 1024];
+    b.iter(|| black_box(slice).iter().fold(None, |_, r| Some(NonNull::from(r))));
+}
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index c4134dbcd25..45e5b76272e 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -960,6 +960,8 @@ pub(crate) mod builtin {
     ///
     /// A compile time error is never emitted when using this macro regardless
     /// of whether the environment variable is present or not.
+    /// To emit a compile error if the environment variable is not present,
+    /// use the [`env!`] macro instead.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 8266e899011..80289ca08c3 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -308,7 +308,7 @@ mod prim_never {}
 ///
 /// ```no_run
 /// // Undefined behaviour
-/// unsafe { char::from_u32_unchecked(0x110000) };
+/// let _ = unsafe { char::from_u32_unchecked(0x110000) };
 /// ```
 ///
 /// USVs are also the exact set of values that may be encoded in UTF-8. Because
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 3462c0e020a..96a145e22ed 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -191,6 +191,39 @@ macro_rules! iterator {
                 self.next_back()
             }
 
+            #[inline]
+            fn fold<B, F>(self, init: B, mut f: F) -> B
+                where
+                    F: FnMut(B, Self::Item) -> B,
+            {
+                // this implementation consists of the following optimizations compared to the
+                // default implementation:
+                // - do-while loop, as is llvm's preferred loop shape,
+                //   see https://releases.llvm.org/16.0.0/docs/LoopTerminology.html#more-canonical-loops
+                // - bumps an index instead of a pointer since the latter case inhibits
+                //   some optimizations, see #111603
+                // - avoids Option wrapping/matching
+                if is_empty!(self) {
+                    return init;
+                }
+                let mut acc = init;
+                let mut i = 0;
+                let len = len!(self);
+                loop {
+                    // SAFETY: the loop iterates `i in 0..len`, which always is in bounds of
+                    // the slice allocation
+                    acc = f(acc, unsafe { & $( $mut_ )? *self.ptr.add(i).as_ptr() });
+                    // SAFETY: `i` can't overflow since it'll only reach usize::MAX if the
+                    // slice had that length, in which case we'll break out of the loop
+                    // after the increment
+                    i = unsafe { i.unchecked_add(1) };
+                    if i == len {
+                        break;
+                    }
+                }
+                acc
+            }
+
             // We override the default implementation, which uses `try_fold`,
             // because this simple implementation generates less LLVM IR and is
             // faster to compile.
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index c02cd99cc44..ee885adfeee 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -1001,7 +1001,7 @@ fn nonnull_tagged_pointer_with_provenance() {
     assert_eq!(p.tag(), 3);
     assert_eq!(unsafe { *p.pointer().as_ptr() }, 10);
 
-    unsafe { Box::from_raw(p.pointer().as_ptr()) };
+    unsafe { drop(Box::from_raw(p.pointer().as_ptr())) };
 
     /// A non-null pointer type which carries several bits of metadata and maintains provenance.
     #[repr(transparent)]
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 8266e899011..80289ca08c3 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -308,7 +308,7 @@ mod prim_never {}
 ///
 /// ```no_run
 /// // Undefined behaviour
-/// unsafe { char::from_u32_unchecked(0x110000) };
+/// let _ = unsafe { char::from_u32_unchecked(0x110000) };
 /// ```
 ///
 /// USVs are also the exact set of values that may be encoded in UTF-8. Because
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index d54a21b9f16..779db9fffa8 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -57,17 +57,11 @@ tidy:
 prepare:
 	$(Q)$(BOOTSTRAP) build --stage 2 nonexistent/path/to/trigger/cargo/metadata
 
-TESTS_IN_2 := \
-	tests/ui \
-	src/tools/linkchecker
-
 ## MSVC native builders
 
-# these intentionally don't use `$(BOOTSTRAP)` so we can test the shebang on Windows
-ci-subset-1:
-	$(Q)$(CFG_SRC_DIR)/x.py test --stage 2 $(TESTS_IN_2:%=--exclude %)
-ci-subset-2:
-	$(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 $(TESTS_IN_2)
+# this intentionally doesn't use `$(BOOTSTRAP)` so we can test the shebang on Windows
+ci-msvc:
+	$(Q)$(CFG_SRC_DIR)/x.py test --stage 2
 
 ## MingW native builders
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index d3cb6b6ed52..19ead2f1b11 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -582,28 +582,16 @@ jobs:
           #  Windows Builders  #
           ######################
 
-          - name: x86_64-msvc-1
+          - name: x86_64-msvc
             env:
               RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
-              SCRIPT: make ci-subset-1
+              SCRIPT: make ci-msvc
             <<: *job-windows-8c
 
-          - name: x86_64-msvc-2
-            env:
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
-              SCRIPT: make ci-subset-2
-            <<: *job-windows-8c
-
-          - name: i686-msvc-1
-            env:
-              RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
-              SCRIPT: make ci-subset-1
-            <<: *job-windows-8c
-
-          - name: i686-msvc-2
+          - name: i686-msvc
             env:
               RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
-              SCRIPT: make ci-subset-2
+              SCRIPT: make ci-msvc
             <<: *job-windows-8c
 
           - name: x86_64-msvc-cargo
diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md
index b512135d927..12a8b2b8db4 100644
--- a/src/doc/rustdoc/src/SUMMARY.md
+++ b/src/doc/rustdoc/src/SUMMARY.md
@@ -7,6 +7,7 @@
 - [How to write documentation](how-to-write-documentation.md)
     - [What to include (and exclude)](write-documentation/what-to-include.md)
     - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
+    - [Re-exports](write-documentation/re-exports.md)
     - [Linking to items by name](write-documentation/linking-to-items-by-name.md)
     - [Documentation tests](write-documentation/documentation-tests.md)
 - [Rustdoc-specific lints](lints.md)
diff --git a/src/doc/rustdoc/src/write-documentation/re-exports.md b/src/doc/rustdoc/src/write-documentation/re-exports.md
new file mode 100644
index 00000000000..593428b8a70
--- /dev/null
+++ b/src/doc/rustdoc/src/write-documentation/re-exports.md
@@ -0,0 +1,172 @@
+# Re-exports
+
+Let's start by explaining what are re-exports. To do so, we will use an example where we are
+writing a library (named `lib`) with some types dispatched in sub-modules:
+
+```rust
+pub mod sub_module1 {
+    pub struct Foo;
+}
+pub mod sub_module2 {
+    pub struct AnotherFoo;
+}
+```
+
+Users can import them like this:
+
+```rust,ignore (inline)
+use lib::sub_module1::Foo;
+use lib::sub_module2::AnotherFoo;
+```
+
+But what if you want the types to be available directly at the crate root or if we don't want the
+modules to be visible for users? That's where re-exports come in:
+
+```rust,ignore (inline)
+// `sub_module1` and `sub_module2` are not visible outside.
+mod sub_module1 {
+    pub struct Foo;
+}
+mod sub_module2 {
+    pub struct AnotherFoo;
+}
+// We re-export both types:
+pub use crate::sub_module1::Foo;
+pub use crate::sub_module2::AnotherFoo;
+```
+
+And now users will be able to do:
+
+```rust,ignore (inline)
+use lib::{Foo, AnotherFoo};
+```
+
+And since both `sub_module1` and `sub_module2` are private, users won't be able to import them.
+
+Now what's interesting is that the generated documentation for this crate will show both `Foo` and
+`AnotherFoo` directly at the crate root, meaning they have been inlined. There are a few rules to
+know whether or not a re-exported item will be inlined.
+
+## Inlining rules
+
+If a public item comes from a private module, it will be inlined:
+
+```rust,ignore (inline)
+mod private_module {
+    pub struct Public;
+}
+pub mod public_mod {
+    // `Public` will inlined here since `private_module` is private.
+    pub use super::private_module::Public;
+}
+// `Public` will not be inlined here since `public_mod` is public.
+pub use self::public_mod::Public;
+```
+
+Likewise, if an item inherits `#[doc(hidden)]` from any of its ancestors, it will be inlined:
+
+```rust,ignore (inline)
+#[doc(hidden)]
+pub mod public_mod {
+    pub struct Public;
+}
+// `Public` be inlined since its parent (`public_mod`) has `#[doc(hidden)]`.
+pub use self::public_mod::Public;
+```
+
+If an item has `#[doc(hidden)]`, it won't be inlined (nor visible in the generated documentation):
+
+```rust,ignore (inline)
+// This struct won't be visible.
+#[doc(hidden)]
+pub struct Hidden;
+
+// This re-export won't be visible.
+pub use self::Hidden as InlinedHidden;
+```
+
+The same applies on re-exports themselves: if you have multiple re-exports and some of them have
+`#[doc(hidden)]`, then these ones (and only these) own't appear in the documentation:
+
+```rust,ignore (inline)
+mod private_mod {
+    /// First
+    pub struct InPrivate;
+}
+
+/// Second
+#[doc(hidden)]
+pub use self::private_mod::InPrivate as Hidden;
+/// Third
+pub use self::Hidden as Visible;
+```
+
+In this case, `InPrivate` will be inlined as `Visible`. However, its documentation will be
+`First Third` and not `First Second Third` because the re-export with `Second` as documentation has
+`#[doc(hidden)]`, therefore, all its attributes are ignored.
+
+## Inlining with `#[doc(inline)]`
+
+You can use the `#[doc(inline)]` attribute if you want to force an item to be inlined:
+
+```rust,ignore (inline)
+pub mod public_mod {
+    pub struct Public;
+}
+#[doc(inline)]
+pub use self::public_mod::Public;
+```
+
+With this code, even though `public_mod::Public` is public and present in the documentation, the
+`Public` type will be present both at the crate root and in the `public_mod` module.
+
+## Preventing inlining with `#[doc(no_inline)]`
+
+On the opposite of the `#[doc(inline)]` attribute, if you want to prevent an item from being
+inlined, you can use `#[doc(no_inline)]`:
+
+```rust,ignore (inline)
+mod private_mod {
+    pub struct Public;
+}
+#[doc(no_inline)]
+pub use self::private_mod::Public;
+```
+
+In the generated documentation, you will see a re-export at the crate root and not the type
+directly.
+
+## Attributes
+
+When an item is inlined, its doc comments and most of its attributes will be inlined along with it:
+
+```rust,ignore (inline)
+mod private_mod {
+    /// First
+    #[cfg(a)]
+    pub struct InPrivate;
+    /// Second
+    #[cfg(b)]
+    pub use self::InPrivate as Second;
+}
+
+/// Third
+#[doc(inline)]
+#[cfg(c)]
+pub use self::private_mod::Second as Visible;
+```
+
+In this case, `Visible` will have as documentation `First Second Third` and will also have as `cfg`:
+`#[cfg(a, b, c)]`.
+
+[Intra-doc links](./linking-to-items-by-name.md) are resolved relative to where the doc comment is
+defined.
+
+There are a few attributes which are not inlined though:
+ * `#[doc(alias="")]`
+ * `#[doc(inline)]`
+ * `#[doc(no_inline)]`
+ * `#[doc(hidden)]` (because the re-export itself and its attributes are ignored).
+
+All other attributes are inherited when inlined, so that the documentation matches the behavior if
+the inlined item was directly defined at the spot where it's shown.
diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
index 8ecf05f0e12..046d018543f 100644
--- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
+++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md
@@ -223,12 +223,18 @@ Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
 One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will
 not eagerly inline it as a module unless you add `#[doc(inline)]`.
 
+If you want to know more about inlining rules, take a look at the
+[`re-exports` chapter](./re-exports.md).
+
 ### `hidden`
 
 <span id="dochidden"></span>
 
 Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless
-the `strip-hidden` pass is removed.
+the `strip-hidden` pass is removed. Re-exported items where one of its ancestors has
+`#[doc(hidden)]` will be considered the same as private.
+
+You can find more information in the [`re-exports` chapter](./re-exports.md).
 
 ### `alias`
 
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
index 575dadde906..ac55ab5a8e2 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.fixed
@@ -2,6 +2,7 @@
 
 #![warn(clippy::transmute_ptr_to_ref)]
 #![allow(clippy::match_single_binding)]
+#![allow(unused_must_use)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = &*p;
@@ -38,7 +39,7 @@ fn _issue1231() {
 
     type Bar<'a> = &'a u8;
     let raw = 42 as *const i32;
-    unsafe { &*(raw as *const u8) };
+    let _ = unsafe { &*(raw as *const u8) };
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
index 4238ff80478..901a3e90dbe 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.rs
@@ -2,6 +2,7 @@
 
 #![warn(clippy::transmute_ptr_to_ref)]
 #![allow(clippy::match_single_binding)]
+#![allow(unused_must_use)]
 
 unsafe fn _ptr_to_ref<T, U>(p: *const T, m: *mut T, o: *const U, om: *mut U) {
     let _: &T = std::mem::transmute(p);
@@ -38,7 +39,7 @@ fn _issue1231() {
 
     type Bar<'a> = &'a u8;
     let raw = 42 as *const i32;
-    unsafe { std::mem::transmute::<_, Bar>(raw) };
+    let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
 }
 
 unsafe fn _issue8924<'a, 'b, 'c>(x: *const &'a u32, y: *const &'b u32) -> &'c &'b u32 {
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
index b3e6c09d2d7..68007edc410 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
@@ -1,5 +1,5 @@
 error: transmute from a pointer type (`*const T`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:7:17
+  --> $DIR/transmute_ptr_to_ref.rs:8:17
    |
 LL |     let _: &T = std::mem::transmute(p);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*p`
@@ -7,127 +7,127 @@ LL |     let _: &T = std::mem::transmute(p);
    = note: `-D clippy::transmute-ptr-to-ref` implied by `-D warnings`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:10:21
+  --> $DIR/transmute_ptr_to_ref.rs:11:21
    |
 LL |     let _: &mut T = std::mem::transmute(m);
    |                     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:13:17
+  --> $DIR/transmute_ptr_to_ref.rs:14:17
    |
 LL |     let _: &T = std::mem::transmute(m);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*m`
 
 error: transmute from a pointer type (`*mut T`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:16:21
+  --> $DIR/transmute_ptr_to_ref.rs:17:21
    |
 LL |     let _: &mut T = std::mem::transmute(p as *mut T);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(p as *mut T)`
 
 error: transmute from a pointer type (`*const U`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:19:17
+  --> $DIR/transmute_ptr_to_ref.rs:20:17
    |
 LL |     let _: &T = std::mem::transmute(o);
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(o as *const T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&mut T`)
-  --> $DIR/transmute_ptr_to_ref.rs:22:21
+  --> $DIR/transmute_ptr_to_ref.rs:23:21
    |
 LL |     let _: &mut T = std::mem::transmute(om);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(om as *mut T)`
 
 error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
-  --> $DIR/transmute_ptr_to_ref.rs:25:17
+  --> $DIR/transmute_ptr_to_ref.rs:26:17
    |
 LL |     let _: &T = std::mem::transmute(om);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
-  --> $DIR/transmute_ptr_to_ref.rs:35:32
+  --> $DIR/transmute_ptr_to_ref.rs:36:32
    |
 LL |     let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
-  --> $DIR/transmute_ptr_to_ref.rs:37:33
+  --> $DIR/transmute_ptr_to_ref.rs:38:33
    |
 LL |     let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<&_>>()`
 
 error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`)
-  --> $DIR/transmute_ptr_to_ref.rs:41:14
+  --> $DIR/transmute_ptr_to_ref.rs:42:22
    |
-LL |     unsafe { std::mem::transmute::<_, Bar>(raw) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
+LL |     let _ = unsafe { std::mem::transmute::<_, Bar>(raw) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const u8)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:46:14
+  --> $DIR/transmute_ptr_to_ref.rs:47:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:47:14
+  --> $DIR/transmute_ptr_to_ref.rs:48:14
    |
 LL |         1 => std::mem::transmute(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:48:14
+  --> $DIR/transmute_ptr_to_ref.rs:49:14
    |
 LL |         2 => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:49:14
+  --> $DIR/transmute_ptr_to_ref.rs:50:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(y),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*y.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:57:19
+  --> $DIR/transmute_ptr_to_ref.rs:58:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:58:19
+  --> $DIR/transmute_ptr_to_ref.rs:59:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a.cast::<u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:60:14
+  --> $DIR/transmute_ptr_to_ref.rs:61:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&u32>()`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:61:14
+  --> $DIR/transmute_ptr_to_ref.rs:62:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*x.cast::<&'b u32>()`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:69:19
+  --> $DIR/transmute_ptr_to_ref.rs:70:19
    |
 LL |     let _: &u32 = std::mem::transmute(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*a`
 
 error: transmute from a pointer type (`*const u32`) to a reference type (`&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:70:19
+  --> $DIR/transmute_ptr_to_ref.rs:71:19
    |
 LL |     let _: &u32 = std::mem::transmute::<_, &u32>(a);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:72:14
+  --> $DIR/transmute_ptr_to_ref.rs:73:14
    |
 LL |         0 => std::mem::transmute(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &u32)`
 
 error: transmute from a pointer type (`*const &u32`) to a reference type (`&&u32`)
-  --> $DIR/transmute_ptr_to_ref.rs:73:14
+  --> $DIR/transmute_ptr_to_ref.rs:74:14
    |
 LL |         _ => std::mem::transmute::<_, &&'b u32>(x),
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(x as *const () as *const &'b u32)`
diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs
index 03113585d14..366930a831c 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs
@@ -10,7 +10,7 @@ fn fill(v: &mut i32) {
 }
 
 fn evil() {
-    unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer
+    let _ = unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer
 }
 
 fn main() {
diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
index 2ba8116cadc..6c41add60ef 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
   --> $DIR/storage_dead_dangling.rs:LL:CC
    |
-LL |     unsafe { &mut *(LEAK as *mut i32) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+LL |     let _ = unsafe { &mut *(LEAK as *mut i32) };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
index e606d8b283c..59781f02366 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
@@ -2,6 +2,6 @@
 
 #[allow(deprecated, invalid_value)]
 fn main() {
-    unsafe { std::mem::uninitialized::<!>() };
+    let _ = unsafe { std::mem::uninitialized::<!>() };
     //~^ ERROR: attempted to instantiate uninhabited type `!`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
index 150128ba2a4..f2cc3430326 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
@@ -1,8 +1,8 @@
 error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!`
   --> $DIR/uninit_uninhabited_type.rs:LL:CC
    |
-LL |     unsafe { std::mem::uninitialized::<!>() };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+LL |     let _ = unsafe { std::mem::uninitialized::<!>() };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
    |
    = note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
index 6d9ae14c5c4..e9c6e464e88 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
@@ -1,5 +1,5 @@
 #[allow(deprecated, invalid_value)]
 fn main() {
-    unsafe { std::mem::zeroed::<fn()>() };
+    let _ = unsafe { std::mem::zeroed::<fn()>() };
     //~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
index 9d44ba9f746..77d58228043 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
@@ -1,8 +1,8 @@
 error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid
   --> $DIR/zero_fn_ptr.rs:LL:CC
    |
-LL |     unsafe { std::mem::zeroed::<fn()>() };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid
+LL |     let _ = unsafe { std::mem::zeroed::<fn()>() };
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid
    |
    = note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC
 
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index 3f60a90f87a..dc902f8cb02 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -14,13 +14,19 @@ fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String>
     if global {
         command.arg("--global");
     }
-    let lines = command
-        .output()
-        .map(|output| String::from_utf8_lossy(&output.stdout).into_owned())
-        .unwrap_or(String::new());
+    let lines = match command.output() {
+        Ok(output) => String::from_utf8_lossy(&output.stdout).into_owned(),
+        Err(e) => {
+            eprintln!(
+                "path to npm can be wrong, provided path: {npm:?}. Try to set npm path \
+            in config.toml in [build.npm]",
+            );
+            panic!("{:?}", e)
+        }
+    };
     lines
         .lines()
-        .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
+        .find_map(|l| l.rsplit(':').next()?.strip_prefix("browser-ui-test@"))
         .map(|v| v.to_owned())
 }
 
diff --git a/tests/codegen/slice-iter-fold.rs b/tests/codegen/slice-iter-fold.rs
new file mode 100644
index 00000000000..9391c176130
--- /dev/null
+++ b/tests/codegen/slice-iter-fold.rs
@@ -0,0 +1,14 @@
+// ignore-debug: the debug assertions get in the way
+// compile-flags: -O
+// min-llvm-version: 16
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @slice_fold_to_last
+#[no_mangle]
+pub fn slice_fold_to_last(slice: &[i32]) -> Option<&i32> {
+    // CHECK-NOT: loop
+    // CHECK-NOT: br
+    // CHECK-NOT: call
+    // CHECK: ret
+    slice.iter().fold(None, |_, i| Some(i))
+}
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index 606d68ff3ab..14fef4e2cd5 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -38,14 +38,6 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
 #[no_mangle]
 pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
     // CHECK-NOT: panic
-
-    // Call to panic_cannot_unwind in case of double-panic is expected,
-    // on LLVM 16 and older, but other panics are not.
-    // old: filter
-    // old-NEXT: ; call core::panicking::panic_cannot_unwind
-    // old-NEXT: panic_cannot_unwind
-
-    // CHECK-NOT: panic
     iter.iter().copied().collect()
 }
 
diff --git a/tests/run-make/panic-abort-eh_frame/Makefile b/tests/run-make/panic-abort-eh_frame/Makefile
new file mode 100644
index 00000000000..1cb7bf575cb
--- /dev/null
+++ b/tests/run-make/panic-abort-eh_frame/Makefile
@@ -0,0 +1,10 @@
+# only-linux
+#
+# This test ensures that `panic=abort` code (without `C-unwind`, that is) should not have any
+# unwinding related `.eh_frame` sections emitted.
+
+include ../tools.mk
+
+all:
+	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort
+	objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA'
diff --git a/tests/run-make/panic-abort-eh_frame/foo.rs b/tests/run-make/panic-abort-eh_frame/foo.rs
new file mode 100644
index 00000000000..e1853529455
--- /dev/null
+++ b/tests/run-make/panic-abort-eh_frame/foo.rs
@@ -0,0 +1,10 @@
+#![no_std]
+
+#[panic_handler]
+fn handler(_: &core::panic::PanicInfo<'_>) -> ! {
+    loop {}
+}
+
+pub unsafe fn oops(x: *const u32) -> u32 {
+    *x
+}
diff --git a/tests/rustdoc/issue-109449-doc-hidden-reexports.rs b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs
new file mode 100644
index 00000000000..b0c22540180
--- /dev/null
+++ b/tests/rustdoc/issue-109449-doc-hidden-reexports.rs
@@ -0,0 +1,143 @@
+// Test to enforce rules over re-exports inlining from
+// <https://github.com/rust-lang/rust/issues/109449>.
+
+#![crate_name = "foo"]
+
+mod private_module {
+    #[doc(hidden)]
+    pub struct Public;
+    #[doc(hidden)]
+    pub type Bar = ();
+}
+
+#[doc(hidden)]
+mod module {
+    pub struct Public2;
+    pub type Bar2 = ();
+}
+
+#[doc(hidden)]
+pub type Bar3 = ();
+#[doc(hidden)]
+pub struct FooFoo;
+
+// Checking that re-exporting a `#[doc(hidden)]` item will NOT inline it.
+pub mod single_reexport {
+    // @has 'foo/single_reexport/index.html'
+
+    // First we check that we have 4 type aliases.
+    // @count - '//*[@id="main-content"]/*[@class="item-table"]//code' 4
+
+    // Then we check that we have the correct link for each re-export.
+
+    // @!has - '//*[@href="struct.Foo.html"]' 'Foo'
+    // @has - '//*[@id="reexport.Foo"]/code' 'pub use crate::private_module::Public as Foo;'
+    pub use crate::private_module::Public as Foo;
+    // @!has - '//*[@href="type.Foo2.html"]' 'Foo2'
+    // @has - '//*[@id="reexport.Foo2"]/code' 'pub use crate::private_module::Bar as Foo2;'
+    pub use crate::private_module::Bar as Foo2;
+    // @!has - '//*[@href="type.Yo.html"]' 'Yo'
+    // @has - '//*[@id="reexport.Yo"]/code' 'pub use crate::Bar3 as Yo;'
+    pub use crate::Bar3 as Yo;
+    // @!has - '//*[@href="struct.Yo2.html"]' 'Yo2'
+    // @has - '//*[@id="reexport.Yo2"]/code' 'pub use crate::FooFoo as Yo2;'
+    pub use crate::FooFoo as Yo2;
+
+    // Checking that each file is also created as expected.
+    // @!has 'foo/single_reexport/struct.Foo.html'
+    // @!has 'foo/single_reexport/type.Foo2.html'
+    // @!has 'foo/single_reexport/type.Yo.html'
+    // @!has 'foo/single_reexport/struct.Yo2.html'
+}
+
+// However, re-exporting an item inheriting `#[doc(hidden)]` will inline it.
+pub mod single_reexport_inherit_hidden {
+    // @has 'foo/single_reexport_inherit_hidden/index.html'
+
+    // @has - '//*[@href="struct.Foo3.html"]' 'Foo3'
+    pub use crate::module::Public2 as Foo3;
+    // @has - '//*[@href="type.Foo4.html"]' 'Foo4'
+    pub use crate::module::Bar2 as Foo4;
+
+    // @has 'foo/single_reexport_inherit_hidden/struct.Foo3.html'
+    // @has 'foo/single_reexport_inherit_hidden/type.Foo4.html'
+}
+
+pub mod single_reexport_no_inline {
+    // First we ensure that we only have re-exports and no inlined items.
+    // @has 'foo/single_reexport_no_inline/index.html'
+    // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 1
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports'
+
+    // Now we check that we don't have links to the items, just `pub use`.
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Public as XFoo;'
+    // @!has - '//*[@id="main-content"]//a' 'XFoo'
+    #[doc(no_inline)]
+    pub use crate::private_module::Public as XFoo;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::private_module::Bar as Foo2;'
+    // @!has - '//*[@id="main-content"]//a' 'Foo2'
+    #[doc(no_inline)]
+    pub use crate::private_module::Bar as Foo2;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::Bar3 as Yo;'
+    // @!has - '//*[@id="main-content"]//a' 'Yo'
+    #[doc(no_inline)]
+    pub use crate::Bar3 as Yo;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::FooFoo as Yo2;'
+    // @!has - '//*[@id="main-content"]//a' 'Yo2'
+    #[doc(no_inline)]
+    pub use crate::FooFoo as Yo2;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::module::Public2 as Foo3;'
+    // @!has - '//*[@id="main-content"]//a' 'Foo3'
+    #[doc(no_inline)]
+    pub use crate::module::Public2 as Foo3;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::module::Bar2 as Foo4;'
+    // @!has - '//*[@id="main-content"]//a' 'Foo4'
+    #[doc(no_inline)]
+    pub use crate::module::Bar2 as Foo4;
+}
+
+// Checking that glob re-exports don't inline `#[doc(hidden)]` items.
+pub mod glob_reexport {
+    // With glob re-exports, we don't inline `#[doc(hidden)]` items so only `module` items
+    // should be inlined.
+    // @has 'foo/glob_reexport/index.html'
+    // @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Re-exports'
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+    // @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Type Definitions'
+
+    // Now we check we have 1 re-export and 2 inlined items.
+    // If not item from a glob re-export is visible, we don't show the re-export.
+    // @!has - '//*[@id="main-content"]//*' 'pub use crate::private_module::*;'
+    pub use crate::private_module::*;
+    // @has - '//*[@id="main-content"]//*' 'pub use crate::*;'
+    pub use crate::*;
+    // This one should be inlined.
+    // @!has - '//*[@id="main-content"]//*' 'pub use crate::module::*;'
+    // @has - '//*[@id="main-content"]//a[@href="struct.Public2.html"]' 'Public2'
+    // @has - '//*[@id="main-content"]//a[@href="type.Bar2.html"]' 'Bar2'
+    // And we check that the two files were created too.
+    // @has 'foo/glob_reexport/struct.Public2.html'
+    // @has 'foo/glob_reexport/type.Bar2.html'
+    pub use crate::module::*;
+}
+
+mod private {
+    /// Original.
+    pub struct Bar3;
+}
+
+// Checking that `#[doc(hidden)]` re-exports documentation isn't generated.
+pub mod doc_hidden_reexport {
+    // @has 'foo/doc_hidden_reexport/index.html'
+    // Ensure there is only one item in this page and that it's a struct.
+    // @count - '//*[@class="item-name"]' 1
+    // @has - '//a[@class="struct"]' 'Reexport'
+    // Check that the `#[doc(hidden)]` re-export's attributes are not taken into account.
+    // @has - '//*[@class="desc docblock-short"]' 'Visible. Original.'
+    /// Hidden.
+    #[doc(hidden)]
+    pub use crate::private::Bar3;
+    /// Visible.
+    pub use self::Bar3 as Reexport;
+}
diff --git a/tests/ui/issues/issue-1460.stderr b/tests/ui/issues/issue-1460.stderr
index eb7661fad56..d4a8c8955e2 100644
--- a/tests/ui/issues/issue-1460.stderr
+++ b/tests/ui/issues/issue-1460.stderr
@@ -1,8 +1,8 @@
 warning: unused closure that must be used
-  --> $DIR/issue-1460.rs:6:5
+  --> $DIR/issue-1460.rs:6:6
    |
 LL |     {|i: u32| if 1 == i { }};
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: closures are lazy and do nothing unless called
    = note: `#[warn(unused_must_use)]` on by default
diff --git a/tests/ui/lint/issue-112489.rs b/tests/ui/lint/issue-112489.rs
new file mode 100644
index 00000000000..559edf0e4f2
--- /dev/null
+++ b/tests/ui/lint/issue-112489.rs
@@ -0,0 +1,17 @@
+// check-pass
+use std::borrow::Borrow;
+
+struct S;
+
+trait T: Sized {
+    fn foo(self) {}
+}
+
+impl T for S {}
+impl T for &S {}
+
+fn main() {
+    let s = S;
+    s.borrow().foo();
+    s.foo();
+}
diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr
index 62cb1f7f4aa..e7c90dcc81b 100644
--- a/tests/ui/lint/type-overflow.stderr
+++ b/tests/ui/lint/type-overflow.stderr
@@ -16,17 +16,33 @@ warning: literal out of range for `i8`
   --> $DIR/type-overflow.rs:10:16
    |
 LL |     let fail = 0b1000_0001i8;
-   |                ^^^^^^^^^^^^^ help: consider using the type `u8` instead: `0b1000_0001u8`
+   |                ^^^^^^^^^^^^^
    |
    = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8`
+help: consider using the type `u8` instead
+   |
+LL |     let fail = 0b1000_0001u8;
+   |                ~~~~~~~~~~~~~
+help: to use as a negative number (decimal `-127`), consider using the type `u8` for the literal and cast it to `i8`
+   |
+LL |     let fail = 0b1000_0001u8 as i8;
+   |                ~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i64`
   --> $DIR/type-overflow.rs:12:16
    |
 LL |     let fail = 0x8000_0000_0000_0000i64;
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x8000_0000_0000_0000u64`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64`
+help: consider using the type `u64` instead
+   |
+LL |     let fail = 0x8000_0000_0000_0000u64;
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+help: to use as a negative number (decimal `-9223372036854775808`), consider using the type `u64` for the literal and cast it to `i64`
+   |
+LL |     let fail = 0x8000_0000_0000_0000u64 as i64;
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `u32`
   --> $DIR/type-overflow.rs:14:16
@@ -44,6 +60,10 @@ LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
    |
    = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128`
    = help: consider using the type `u128` instead
+help: to use as a negative number (decimal `-170141183460469231731687303715884105728`), consider using the type `u128` for the literal and cast it to `i128`
+   |
+LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128;
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i32`
   --> $DIR/type-overflow.rs:19:16
@@ -53,6 +73,10 @@ LL |     let fail = 0x8FFF_FFFF_FFFF_FFFE;
    |
    = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
    = help: consider using the type `i128` instead
+help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32`
+   |
+LL |     let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32;
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i8`
   --> $DIR/type-overflow.rs:21:17
diff --git a/tests/ui/lint/unused/must-use-block-expr.fixed b/tests/ui/lint/unused/must-use-block-expr.fixed
new file mode 100644
index 00000000000..642012812bd
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-block-expr.fixed
@@ -0,0 +1,36 @@
+// run-rustfix
+// check-pass
+
+#![warn(unused_must_use)]
+
+#[must_use]
+fn foo() -> i32 {
+    42
+}
+
+fn bar() {
+    {
+        let _ = foo();
+        //~^ WARN unused return value
+    }
+}
+
+fn baz() {
+    {
+        let _ = foo();
+        //~^ WARN unused return value
+    };
+}
+
+fn main() {
+    bar();
+    baz();
+    {
+        let _ = 1 + 2;
+        //~^ WARN unused arithmetic operation
+    }
+    {
+        let _ = 1 + 2;
+        //~^ WARN unused arithmetic operation
+    };
+}
diff --git a/tests/ui/lint/unused/must-use-block-expr.rs b/tests/ui/lint/unused/must-use-block-expr.rs
new file mode 100644
index 00000000000..e0a680aa07d
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-block-expr.rs
@@ -0,0 +1,36 @@
+// run-rustfix
+// check-pass
+
+#![warn(unused_must_use)]
+
+#[must_use]
+fn foo() -> i32 {
+    42
+}
+
+fn bar() {
+    {
+        foo();
+        //~^ WARN unused return value
+    }
+}
+
+fn baz() {
+    {
+        foo()
+        //~^ WARN unused return value
+    };
+}
+
+fn main() {
+    bar();
+    baz();
+    {
+        1 + 2;
+        //~^ WARN unused arithmetic operation
+    }
+    {
+        1 + 2
+        //~^ WARN unused arithmetic operation
+    };
+}
diff --git a/tests/ui/lint/unused/must-use-block-expr.stderr b/tests/ui/lint/unused/must-use-block-expr.stderr
new file mode 100644
index 00000000000..d821beb1d92
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-block-expr.stderr
@@ -0,0 +1,51 @@
+warning: unused return value of `foo` that must be used
+  --> $DIR/must-use-block-expr.rs:13:9
+   |
+LL |         foo();
+   |         ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/must-use-block-expr.rs:4:9
+   |
+LL | #![warn(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the resulting value
+   |
+LL |         let _ = foo();
+   |         +++++++
+
+warning: unused return value of `foo` that must be used
+  --> $DIR/must-use-block-expr.rs:20:9
+   |
+LL |         foo()
+   |         ^^^^^
+   |
+help: use `let _ = ...` to ignore the resulting value
+   |
+LL |         let _ = foo();
+   |         +++++++      +
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-block-expr.rs:29:9
+   |
+LL |         1 + 2;
+   |         ^^^^^ the arithmetic operation produces a value
+   |
+help: use `let _ = ...` to ignore the resulting value
+   |
+LL |         let _ = 1 + 2;
+   |         +++++++
+
+warning: unused arithmetic operation that must be used
+  --> $DIR/must-use-block-expr.rs:33:9
+   |
+LL |         1 + 2
+   |         ^^^^^ the arithmetic operation produces a value
+   |
+help: use `let _ = ...` to ignore the resulting value
+   |
+LL |         let _ = 1 + 2;
+   |         +++++++      +
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs
new file mode 100644
index 00000000000..15f380f7fb4
--- /dev/null
+++ b/tests/ui/match/issue-112438.rs
@@ -0,0 +1,11 @@
+// run-pass
+#![feature(inline_const_pat)]
+#![allow(dead_code)]
+#![allow(incomplete_features)]
+fn foo<const V: usize>() {
+    match 0 {
+        const { 1 << 5 } | _ => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-112472-multi-generics-suggestion.fixed b/tests/ui/resolve/issue-112472-multi-generics-suggestion.fixed
new file mode 100644
index 00000000000..892697493b7
--- /dev/null
+++ b/tests/ui/resolve/issue-112472-multi-generics-suggestion.fixed
@@ -0,0 +1,31 @@
+// run-rustfix
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::convert::{self, TryFrom};
+
+#[allow(unused)]
+struct Codec<EncodeLine, DecodeLine> {
+    phantom_decode: PhantomData<DecodeLine>,
+    phantom_encode: PhantomData<EncodeLine>,
+}
+
+pub enum ParseError {}
+
+impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
+    DecodeLine: Debug + convert::TryFrom<String>,
+    DecodeLine: convert::TryFrom<String, Error = ParseError>,
+    //~^ ERROR expected trait, found enum `ParseError`
+    //~| HELP constrain the associated type to `ParseError`
+{
+}
+
+impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
+    DecodeLine: Debug + TryFrom<String>,
+    DecodeLine: TryFrom<String, Error = ParseError>,
+    //~^ ERROR expected trait, found enum `ParseError`
+    //~| HELP constrain the associated type to `ParseError`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-112472-multi-generics-suggestion.rs b/tests/ui/resolve/issue-112472-multi-generics-suggestion.rs
new file mode 100644
index 00000000000..2b2f5f1ad8d
--- /dev/null
+++ b/tests/ui/resolve/issue-112472-multi-generics-suggestion.rs
@@ -0,0 +1,31 @@
+// run-rustfix
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::convert::{self, TryFrom};
+
+#[allow(unused)]
+struct Codec<EncodeLine, DecodeLine> {
+    phantom_decode: PhantomData<DecodeLine>,
+    phantom_encode: PhantomData<EncodeLine>,
+}
+
+pub enum ParseError {}
+
+impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
+    DecodeLine: Debug + convert::TryFrom<String>,
+    <DecodeLine as convert::TryFrom<String>>::Error: ParseError,
+    //~^ ERROR expected trait, found enum `ParseError`
+    //~| HELP constrain the associated type to `ParseError`
+{
+}
+
+impl<EncodeLine, DecodeLine> Codec<EncodeLine, DecodeLine> where
+    DecodeLine: Debug + TryFrom<String>,
+    <DecodeLine as TryFrom<String>>::Error: ParseError,
+    //~^ ERROR expected trait, found enum `ParseError`
+    //~| HELP constrain the associated type to `ParseError`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-112472-multi-generics-suggestion.stderr b/tests/ui/resolve/issue-112472-multi-generics-suggestion.stderr
new file mode 100644
index 00000000000..f463e2dad2c
--- /dev/null
+++ b/tests/ui/resolve/issue-112472-multi-generics-suggestion.stderr
@@ -0,0 +1,25 @@
+error[E0404]: expected trait, found enum `ParseError`
+  --> $DIR/issue-112472-multi-generics-suggestion.rs:17:54
+   |
+LL |     <DecodeLine as convert::TryFrom<String>>::Error: ParseError,
+   |                                                      ^^^^^^^^^^ not a trait
+   |
+help: constrain the associated type to `ParseError`
+   |
+LL |     DecodeLine: convert::TryFrom<String, Error = ParseError>,
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0404]: expected trait, found enum `ParseError`
+  --> $DIR/issue-112472-multi-generics-suggestion.rs:25:45
+   |
+LL |     <DecodeLine as TryFrom<String>>::Error: ParseError,
+   |                                             ^^^^^^^^^^ not a trait
+   |
+help: constrain the associated type to `ParseError`
+   |
+LL |     DecodeLine: TryFrom<String, Error = ParseError>,
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0404`.