about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-21 00:46:30 +0000
committerbors <bors@rust-lang.org>2024-05-21 00:46:30 +0000
commit8e7517d99a8aaab02b512483ae91f8b79553fa3d (patch)
tree5ea87447eb3301f4f5248921740fef70842bfebd
parent60faa271d9f11474caa68de6fe44ff502437f9e1 (diff)
parent63fa01eb094a5894fb3d9c776426749c8372f94e (diff)
downloadrust-8e7517d99a8aaab02b512483ae91f8b79553fa3d.tar.gz
rust-8e7517d99a8aaab02b512483ae91f8b79553fa3d.zip
Auto merge of #125349 - matthiaskrgr:rollup-p2mbdxi, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #124050 (Remove libc from MSVC targets)
 - #124283 (Note for E0599 if shadowed bindings has the method.)
 - #125123 (Fix `read_exact` and `read_buf_exact` for `&[u8]` and `io:Cursor`)
 - #125158 (hir pretty: fix block indent)
 - #125308 (track cycle participants per root)
 - #125332 (Update books)
 - #125333 (switch to the default implementation of `write_vectored`)
 - #125346 (Remove some `Path::to_str` from `rustc_codegen_llvm`)

Failed merges:

 - #125310 (Move ~100 tests from tests/ui to subdirs)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs29
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs213
-rw-r--r--compiler/rustc_middle/src/traits/solve/cache.rs34
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs377
-rw-r--r--library/std/Cargo.toml3
-rw-r--r--library/std/src/io/cursor.rs27
-rw-r--r--library/std/src/io/impls.rs6
-rw-r--r--library/std/src/io/tests.rs32
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/raw/tests.rs2
-rw-r--r--library/std/src/sys/pal/hermit/net.rs25
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--tests/incremental/foreign.rs27
-rw-r--r--tests/pretty/issue-4264.pp46
-rw-r--r--tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs5
-rw-r--r--tests/run-make/link-path-order/main.rs6
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.stderr8
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-2.stderr8
-rw-r--r--tests/ui/env-null-vars.rs14
-rw-r--r--tests/ui/error-codes/E0259.rs4
-rw-r--r--tests/ui/error-codes/E0259.stderr4
-rw-r--r--tests/ui/feature-gates/rustc-private.rs2
-rw-r--r--tests/ui/feature-gates/rustc-private.stderr4
-rw-r--r--tests/ui/foreign/foreign-fn-linkname.rs10
-rw-r--r--tests/ui/foreign/foreign2.rs30
-rw-r--r--tests/ui/imports/issue-37887.rs4
-rw-r--r--tests/ui/imports/issue-37887.stderr16
-rw-r--r--tests/ui/lint/unnecessary-extern-crate.rs14
-rw-r--r--tests/ui/lint/unnecessary-extern-crate.stderr12
-rw-r--r--tests/ui/match/issue-82392.stdout14
-rw-r--r--tests/ui/meta/no_std-extern-libc.rs1
-rw-r--r--tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.rs7
-rw-r--r--tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.stderr17
-rw-r--r--tests/ui/process/no-stdio.rs8
-rw-r--r--tests/ui/runtime/on-broken-pipe/error.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/inherit.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/kill.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/not-used.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/with-rustc_main.rs1
-rw-r--r--tests/ui/runtime/out-of-stack.rs7
-rw-r--r--tests/ui/runtime/stdout-during-shutdown-unix.rs (renamed from tests/ui/runtime/stdout-during-shutdown.rs)1
-rw-r--r--tests/ui/runtime/stdout-during-shutdown-unix.run.stdout (renamed from tests/ui/runtime/stdout-during-shutdown.run.stdout)0
-rw-r--r--tests/ui/runtime/stdout-during-shutdown-windows.rs20
-rw-r--r--tests/ui/runtime/stdout-during-shutdown-windows.run.stdout1
-rw-r--r--tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr4
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr (renamed from tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr)6
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr26
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60662.stdout4
-rw-r--r--tests/ui/unpretty/bad-literal.stdout4
-rw-r--r--tests/ui/unpretty/box.stdout8
-rw-r--r--tests/ui/unpretty/flattened-format-args.stdout14
-rw-r--r--tests/ui/unpretty/let-else-hir.stdout10
-rw-r--r--tests/ui/wait-forked-but-failed-child.rs3
61 files changed, 772 insertions, 357 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index d4a3e39cef7..c304c0cbd3b 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -200,21 +200,20 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                 _ => panic!("unsupported arch {}", sess.target.arch),
             };
             let mut dlltool_cmd = std::process::Command::new(&dlltool);
-            dlltool_cmd.args([
-                "-d",
-                def_file_path.to_str().unwrap(),
-                "-D",
-                lib_name,
-                "-l",
-                output_path.to_str().unwrap(),
-                "-m",
-                dlltool_target_arch,
-                "-f",
-                dlltool_target_bitness,
-                "--no-leading-underscore",
-                "--temp-prefix",
-                temp_prefix.to_str().unwrap(),
-            ]);
+            dlltool_cmd
+                .arg("-d")
+                .arg(def_file_path)
+                .arg("-D")
+                .arg(lib_name)
+                .arg("-l")
+                .arg(&output_path)
+                .arg("-m")
+                .arg(dlltool_target_arch)
+                .arg("-f")
+                .arg(dlltool_target_bitness)
+                .arg("--no-leading-underscore")
+                .arg("--temp-prefix")
+                .arg(temp_prefix);
 
             match dlltool_cmd.output() {
                 Err(e) => {
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 29c7e576d2b..488537e81be 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1454,7 +1454,7 @@ impl<'a> State<'a> {
                     self.word_space(":");
                 }
                 // containing cbox, will be closed by print-block at `}`
-                self.cbox(INDENT_UNIT);
+                self.cbox(0);
                 // head-box, will be closed by print-block after `{`
                 self.ibox(0);
                 self.print_block(blk);
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index fb7d3f40093..fade943c5ae 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1346,6 +1346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if segment.ident.name != kw::Empty {
                     if let Some(err) = self.report_method_error(
                         span,
+                        Some(rcvr),
                         rcvr_t,
                         segment.ident,
                         SelfSource::MethodCall(rcvr),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6e8ef044452..758df83d3eb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -834,6 +834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if item_name.name != kw::Empty {
                     if let Some(e) = self.report_method_error(
                         span,
+                        None,
                         ty.normalized,
                         item_name,
                         SelfSource::QPath(qself),
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index db510d44392..54af8354c4c 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -7,6 +7,7 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
 use crate::Expectation;
 use crate::FnCtxt;
 use core::ops::ControlFlow;
+use hir::Expr;
 use rustc_ast::ast::Mutability;
 use rustc_attr::parse_confusables;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -19,7 +20,6 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::PatKind::Binding;
 use rustc_hir::PathSegment;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::{self, RegionVariableOrigin};
@@ -46,7 +46,7 @@ use std::borrow::Cow;
 
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
-use rustc_hir::intravisit::Visitor;
+use rustc_hir::intravisit::{self, Visitor};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
@@ -188,6 +188,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn report_method_error(
         &self,
         span: Span,
+        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
@@ -212,6 +213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             MethodError::NoMatch(mut no_match_data) => {
                 return self.report_no_match_method_error(
                     span,
+                    rcvr_opt,
                     rcvr_ty,
                     item_name,
                     source,
@@ -356,9 +358,197 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err
     }
 
+    pub fn suggest_use_shadowed_binding_with_method(
+        &self,
+        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
+        method_name: Ident,
+        ty_str_reported: &str,
+        err: &mut Diag<'_>,
+    ) {
+        #[derive(Debug)]
+        struct LetStmt {
+            ty_hir_id_opt: Option<hir::HirId>,
+            binding_id: hir::HirId,
+            span: Span,
+            init_hir_id: hir::HirId,
+        }
+
+        // Used for finding suggest binding.
+        // ```rust
+        // earlier binding for suggesting:
+        // let y = vec![1, 2];
+        // now binding:
+        // if let Some(y) = x {
+        //     y.push(y);
+        // }
+        // ```
+        struct LetVisitor<'a, 'tcx> {
+            // Error binding which don't have `method_name`.
+            binding_name: Symbol,
+            binding_id: hir::HirId,
+            // Used for check if the suggest binding has `method_name`.
+            fcx: &'a FnCtxt<'a, 'tcx>,
+            call_expr: &'tcx Expr<'tcx>,
+            method_name: Ident,
+            // Suggest the binding which is shallowed.
+            sugg_let: Option<LetStmt>,
+        }
+
+        impl<'a, 'tcx> LetVisitor<'a, 'tcx> {
+            // Check scope of binding.
+            fn is_sub_scope(&self, sub_id: hir::ItemLocalId, super_id: hir::ItemLocalId) -> bool {
+                let scope_tree = self.fcx.tcx.region_scope_tree(self.fcx.body_id);
+                if let Some(sub_var_scope) = scope_tree.var_scope(sub_id)
+                    && let Some(super_var_scope) = scope_tree.var_scope(super_id)
+                    && scope_tree.is_subscope_of(sub_var_scope, super_var_scope)
+                {
+                    return true;
+                }
+                false
+            }
+
+            // Check if an earlier shadowed binding make `the receiver` of a MethodCall has the method.
+            // If it does, record the earlier binding for subsequent notes.
+            fn check_and_add_sugg_binding(&mut self, binding: LetStmt) -> bool {
+                if !self.is_sub_scope(self.binding_id.local_id, binding.binding_id.local_id) {
+                    return false;
+                }
+
+                // Get the earlier shadowed binding'ty and use it to check the method.
+                if let Some(ty_hir_id) = binding.ty_hir_id_opt
+                    && let Some(tyck_ty) = self.fcx.node_ty_opt(ty_hir_id)
+                {
+                    if self
+                        .fcx
+                        .lookup_probe_for_diagnostic(
+                            self.method_name,
+                            tyck_ty,
+                            self.call_expr,
+                            ProbeScope::TraitsInScope,
+                            None,
+                        )
+                        .is_ok()
+                    {
+                        self.sugg_let = Some(binding);
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+
+                // If the shadowed binding has an an itializer expression,
+                // use the initializer expression'ty to try to find the method again.
+                // For example like:  `let mut x = Vec::new();`,
+                // `Vec::new()` is the itializer expression.
+                if let Some(self_ty) = self.fcx.node_ty_opt(binding.init_hir_id)
+                    && self
+                        .fcx
+                        .lookup_probe_for_diagnostic(
+                            self.method_name,
+                            self_ty,
+                            self.call_expr,
+                            ProbeScope::TraitsInScope,
+                            None,
+                        )
+                        .is_ok()
+                {
+                    self.sugg_let = Some(binding);
+                    return true;
+                }
+                return false;
+            }
+        }
+
+        impl<'v> Visitor<'v> for LetVisitor<'_, '_> {
+            type Result = ControlFlow<()>;
+            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
+                if let hir::StmtKind::Let(&hir::LetStmt { pat, ty, init, .. }) = ex.kind
+                    && let hir::PatKind::Binding(_, binding_id, binding_name, ..) = pat.kind
+                    && let Some(init) = init
+                    && binding_name.name == self.binding_name
+                    && binding_id != self.binding_id
+                {
+                    if self.check_and_add_sugg_binding(LetStmt {
+                        ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None },
+                        binding_id: binding_id,
+                        span: pat.span,
+                        init_hir_id: init.hir_id,
+                    }) {
+                        return ControlFlow::Break(());
+                    }
+                    ControlFlow::Continue(())
+                } else {
+                    hir::intravisit::walk_stmt(self, ex)
+                }
+            }
+
+            // Used for find the error binding.
+            // When the visitor reaches this point, all the shadowed bindings
+            // have been found, so the visitor ends.
+            fn visit_pat(&mut self, p: &'v hir::Pat<'v>) -> Self::Result {
+                match p.kind {
+                    hir::PatKind::Binding(_, binding_id, binding_name, _) => {
+                        if binding_name.name == self.binding_name && binding_id == self.binding_id {
+                            return ControlFlow::Break(());
+                        }
+                    }
+                    _ => {
+                        intravisit::walk_pat(self, p);
+                    }
+                }
+                ControlFlow::Continue(())
+            }
+        }
+
+        if let Some(rcvr) = rcvr_opt
+            && let hir::ExprKind::Path(QPath::Resolved(_, path)) = rcvr.kind
+            && let hir::def::Res::Local(recv_id) = path.res
+            && let Some(segment) = path.segments.first()
+        {
+            let map = self.infcx.tcx.hir();
+            let body_id = self.tcx.hir().body_owned_by(self.body_id);
+            let body = map.body(body_id);
+
+            if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) {
+                let mut let_visitor = LetVisitor {
+                    fcx: self,
+                    call_expr,
+                    binding_name: segment.ident.name,
+                    binding_id: recv_id,
+                    method_name,
+                    sugg_let: None,
+                };
+                let_visitor.visit_body(body);
+                if let Some(sugg_let) = let_visitor.sugg_let
+                    && let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id)
+                {
+                    let _sm = self.infcx.tcx.sess.source_map();
+                    let rcvr_name = segment.ident.name;
+                    let mut span = MultiSpan::from_span(sugg_let.span);
+                    span.push_span_label(sugg_let.span,
+                            format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
+                    span.push_span_label(
+                        self.tcx.hir().span(recv_id),
+                        format!(
+                            "earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
+                        ),
+                    );
+                    err.span_note(
+                        span,
+                        format!(
+                            "there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
+                                    that has method `{method_name}` available"
+                        ),
+                    );
+                }
+            }
+        }
+    }
+
     pub fn report_no_match_method_error(
         &self,
         mut span: Span,
+        rcvr_opt: Option<&'tcx hir::Expr<'tcx>>,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
@@ -451,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
             self.suggest_missing_writer(rcvr_ty, rcvr_expr)
         } else {
-            tcx.dcx().create_err(NoAssociatedItem {
+            let mut err = tcx.dcx().create_err(NoAssociatedItem {
                 span,
                 item_kind,
                 item_name,
@@ -461,9 +651,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     rcvr_ty.prefix_string(self.tcx)
                 },
-                ty_str: ty_str_reported,
+                ty_str: ty_str_reported.clone(),
                 trait_missing_method,
-            })
+            });
+
+            if is_method {
+                self.suggest_use_shadowed_binding_with_method(
+                    rcvr_opt,
+                    item_name,
+                    &ty_str_reported,
+                    &mut err,
+                );
+            }
+
+            err
         };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
@@ -2240,7 +2441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     type Result = ControlFlow<Option<&'v hir::Expr<'v>>>;
                     fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
                         if let hir::StmtKind::Let(&hir::LetStmt { pat, init, .. }) = ex.kind
-                            && let Binding(_, _, ident, ..) = pat.kind
+                            && let hir::PatKind::Binding(_, _, ident, ..) = pat.kind
                             && ident.name == self.ident_name
                         {
                             ControlFlow::Break(init)
diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs
index 03ce7cf98cf..2ff4ade21d0 100644
--- a/compiler/rustc_middle/src/traits/solve/cache.rs
+++ b/compiler/rustc_middle/src/traits/solve/cache.rs
@@ -14,11 +14,11 @@ pub struct EvaluationCache<'tcx> {
     map: Lock<FxHashMap<CanonicalInput<'tcx>, CacheEntry<'tcx>>>,
 }
 
-#[derive(PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq)]
 pub struct CacheData<'tcx> {
     pub result: QueryResult<'tcx>,
     pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
-    pub reached_depth: usize,
+    pub additional_depth: usize,
     pub encountered_overflow: bool,
 }
 
@@ -29,7 +29,7 @@ impl<'tcx> EvaluationCache<'tcx> {
         tcx: TyCtxt<'tcx>,
         key: CanonicalInput<'tcx>,
         proof_tree: Option<&'tcx [inspect::GoalEvaluationStep<TyCtxt<'tcx>>]>,
-        reached_depth: usize,
+        additional_depth: usize,
         encountered_overflow: bool,
         cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
         dep_node: DepNodeIndex,
@@ -40,17 +40,17 @@ impl<'tcx> EvaluationCache<'tcx> {
         let data = WithDepNode::new(dep_node, QueryData { result, proof_tree });
         entry.cycle_participants.extend(cycle_participants);
         if encountered_overflow {
-            entry.with_overflow.insert(reached_depth, data);
+            entry.with_overflow.insert(additional_depth, data);
         } else {
-            entry.success = Some(Success { data, reached_depth });
+            entry.success = Some(Success { data, additional_depth });
         }
 
         if cfg!(debug_assertions) {
             drop(map);
-            if Some(CacheData { result, proof_tree, reached_depth, encountered_overflow })
-                != self.get(tcx, key, |_| false, Limit(reached_depth))
-            {
-                bug!("unable to retrieve inserted element from cache: {key:?}");
+            let expected = CacheData { result, proof_tree, additional_depth, encountered_overflow };
+            let actual = self.get(tcx, key, [], Limit(additional_depth));
+            if !actual.as_ref().is_some_and(|actual| expected == *actual) {
+                bug!("failed to lookup inserted element for {key:?}: {expected:?} != {actual:?}");
             }
         }
     }
@@ -63,23 +63,25 @@ impl<'tcx> EvaluationCache<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
         key: CanonicalInput<'tcx>,
-        cycle_participant_in_stack: impl FnOnce(&FxHashSet<CanonicalInput<'tcx>>) -> bool,
+        stack_entries: impl IntoIterator<Item = CanonicalInput<'tcx>>,
         available_depth: Limit,
     ) -> Option<CacheData<'tcx>> {
         let map = self.map.borrow();
         let entry = map.get(&key)?;
 
-        if cycle_participant_in_stack(&entry.cycle_participants) {
-            return None;
+        for stack_entry in stack_entries {
+            if entry.cycle_participants.contains(&stack_entry) {
+                return None;
+            }
         }
 
         if let Some(ref success) = entry.success {
-            if available_depth.value_within_limit(success.reached_depth) {
+            if available_depth.value_within_limit(success.additional_depth) {
                 let QueryData { result, proof_tree } = success.data.get(tcx);
                 return Some(CacheData {
                     result,
                     proof_tree,
-                    reached_depth: success.reached_depth,
+                    additional_depth: success.additional_depth,
                     encountered_overflow: false,
                 });
             }
@@ -90,7 +92,7 @@ impl<'tcx> EvaluationCache<'tcx> {
             CacheData {
                 result,
                 proof_tree,
-                reached_depth: available_depth.0,
+                additional_depth: available_depth.0,
                 encountered_overflow: true,
             }
         })
@@ -99,7 +101,7 @@ impl<'tcx> EvaluationCache<'tcx> {
 
 struct Success<'tcx> {
     data: WithDepNode<QueryData<'tcx>>,
-    reached_depth: usize,
+    additional_depth: usize,
 }
 
 #[derive(Clone, Copy)]
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index 5a5df439a78..bcd210f789b 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -47,20 +47,39 @@ struct StackEntry<I: Interner> {
     /// Whether this entry is a non-root cycle participant.
     ///
     /// We must not move the result of non-root cycle participants to the
-    /// global cache. See [SearchGraph::cycle_participants] for more details.
-    /// We store the highest stack depth of a head of a cycle this goal is involved
-    /// in. This necessary to soundly cache its provisional result.
+    /// global cache. We store the highest stack depth of a head of a cycle
+    /// this goal is involved in. This necessary to soundly cache its
+    /// provisional result.
     non_root_cycle_participant: Option<StackDepth>,
 
     encountered_overflow: bool,
 
     has_been_used: HasBeenUsed,
+
+    /// We put only the root goal of a coinductive cycle into the global cache.
+    ///
+    /// If we were to use that result when later trying to prove another cycle
+    /// participant, we can end up with unstable query results.
+    ///
+    /// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for
+    /// an example of where this is needed.
+    ///
+    /// There can  be multiple roots on the same stack, so we need to track
+    /// cycle participants per root:
+    /// ```plain
+    /// A :- B
+    /// B :- A, C
+    /// C :- D
+    /// D :- C
+    /// ```
+    cycle_participants: FxHashSet<CanonicalInput<I>>,
     /// Starts out as `None` and gets set when rerunning this
     /// goal in case we encounter a cycle.
     provisional_result: Option<QueryResult<I>>,
 }
 
 /// The provisional result for a goal which is not on the stack.
+#[derive(Debug)]
 struct DetachedEntry<I: Interner> {
     /// The head of the smallest non-trivial cycle involving this entry.
     ///
@@ -110,40 +129,17 @@ pub(super) struct SearchGraph<I: Interner> {
     /// An element is *deeper* in the stack if its index is *lower*.
     stack: IndexVec<StackDepth, StackEntry<I>>,
     provisional_cache: FxHashMap<CanonicalInput<I>, ProvisionalCacheEntry<I>>,
-    /// We put only the root goal of a coinductive cycle into the global cache.
-    ///
-    /// If we were to use that result when later trying to prove another cycle
-    /// participant, we can end up with unstable query results.
-    ///
-    /// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for
-    /// an example of where this is needed.
-    cycle_participants: FxHashSet<CanonicalInput<I>>,
 }
 
 impl<I: Interner> SearchGraph<I> {
     pub(super) fn new(mode: SolverMode) -> SearchGraph<I> {
-        Self {
-            mode,
-            stack: Default::default(),
-            provisional_cache: Default::default(),
-            cycle_participants: Default::default(),
-        }
+        Self { mode, stack: Default::default(), provisional_cache: Default::default() }
     }
 
     pub(super) fn solver_mode(&self) -> SolverMode {
         self.mode
     }
 
-    /// Update the stack and reached depths on cache hits.
-    #[instrument(level = "trace", skip(self))]
-    fn on_cache_hit(&mut self, additional_depth: usize, encountered_overflow: bool) {
-        let reached_depth = self.stack.next_index().plus(additional_depth);
-        if let Some(last) = self.stack.raw.last_mut() {
-            last.reached_depth = last.reached_depth.max(reached_depth);
-            last.encountered_overflow |= encountered_overflow;
-        }
-    }
-
     /// Pops the highest goal from the stack, lazily updating the
     /// the next goal in the stack.
     ///
@@ -159,13 +155,7 @@ impl<I: Interner> SearchGraph<I> {
     }
 
     pub(super) fn is_empty(&self) -> bool {
-        if self.stack.is_empty() {
-            debug_assert!(self.provisional_cache.is_empty());
-            debug_assert!(self.cycle_participants.is_empty());
-            true
-        } else {
-            false
-        }
+        self.stack.is_empty()
     }
 
     /// Returns the remaining depth allowed for nested goals.
@@ -215,15 +205,26 @@ impl<I: Interner> SearchGraph<I> {
     // their result does not get moved to the global cache.
     fn tag_cycle_participants(
         stack: &mut IndexVec<StackDepth, StackEntry<I>>,
-        cycle_participants: &mut FxHashSet<CanonicalInput<I>>,
         usage_kind: HasBeenUsed,
         head: StackDepth,
     ) {
         stack[head].has_been_used |= usage_kind;
         debug_assert!(!stack[head].has_been_used.is_empty());
-        for entry in &mut stack.raw[head.index() + 1..] {
+
+        // The current root of these cycles. Note that this may not be the final
+        // root in case a later goal depends on a goal higher up the stack.
+        let mut current_root = head;
+        while let Some(parent) = stack[current_root].non_root_cycle_participant {
+            current_root = parent;
+            debug_assert!(!stack[current_root].has_been_used.is_empty());
+        }
+
+        let (stack, cycle_participants) = stack.raw.split_at_mut(head.index() + 1);
+        let current_cycle_root = &mut stack[current_root.as_usize()];
+        for entry in cycle_participants {
             entry.non_root_cycle_participant = entry.non_root_cycle_participant.max(Some(head));
-            cycle_participants.insert(entry.input);
+            current_cycle_root.cycle_participants.insert(entry.input);
+            current_cycle_root.cycle_participants.extend(mem::take(&mut entry.cycle_participants));
         }
     }
 
@@ -266,6 +267,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
             &mut ProofTreeBuilder<TyCtxt<'tcx>>,
         ) -> QueryResult<TyCtxt<'tcx>>,
     ) -> QueryResult<TyCtxt<'tcx>> {
+        self.check_invariants();
         // Check for overflow.
         let Some(available_depth) = Self::allowed_depth_for_nested(tcx, &self.stack) else {
             if let Some(last) = self.stack.raw.last_mut() {
@@ -276,37 +278,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
             return Self::response_no_constraints(tcx, input, Certainty::overflow(true));
         };
 
-        // Try to fetch the goal from the global cache.
-        'global: {
-            let Some(CacheData { result, proof_tree, reached_depth, encountered_overflow }) =
-                self.global_cache(tcx).get(
-                    tcx,
-                    input,
-                    |cycle_participants| {
-                        self.stack.iter().any(|entry| cycle_participants.contains(&entry.input))
-                    },
-                    available_depth,
-                )
-            else {
-                break 'global;
-            };
-
-            // If we're building a proof tree and the current cache entry does not
-            // contain a proof tree, we do not use the entry but instead recompute
-            // the goal. We simply overwrite the existing entry once we're done,
-            // caching the proof tree.
-            if !inspect.is_noop() {
-                if let Some(revisions) = proof_tree {
-                    inspect.goal_evaluation_kind(
-                        inspect::WipCanonicalGoalEvaluationKind::Interned { revisions },
-                    );
-                } else {
-                    break 'global;
-                }
-            }
-
-            self.on_cache_hit(reached_depth, encountered_overflow);
-            debug!("global cache hit");
+        if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) {
             return result;
         }
 
@@ -332,12 +304,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
             // already set correctly while computing the cache entry.
             inspect
                 .goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit);
-            Self::tag_cycle_participants(
-                &mut self.stack,
-                &mut self.cycle_participants,
-                HasBeenUsed::empty(),
-                entry.head,
-            );
+            Self::tag_cycle_participants(&mut self.stack, HasBeenUsed::empty(), entry.head);
             return entry.result;
         } else if let Some(stack_depth) = cache_entry.stack_depth {
             debug!("encountered cycle with depth {stack_depth:?}");
@@ -354,12 +321,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
             } else {
                 HasBeenUsed::INDUCTIVE_CYCLE
             };
-            Self::tag_cycle_participants(
-                &mut self.stack,
-                &mut self.cycle_participants,
-                usage_kind,
-                stack_depth,
-            );
+            Self::tag_cycle_participants(&mut self.stack, usage_kind, stack_depth);
 
             // Return the provisional result or, if we're in the first iteration,
             // start with no constraints.
@@ -380,6 +342,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
                 non_root_cycle_participant: None,
                 encountered_overflow: false,
                 has_been_used: HasBeenUsed::empty(),
+                cycle_participants: Default::default(),
                 provisional_result: None,
             };
             assert_eq!(self.stack.push(entry), depth);
@@ -388,63 +351,16 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
 
         // This is for global caching, so we properly track query dependencies.
         // Everything that affects the `result` should be performed within this
-        // `with_anon_task` closure.
+        // `with_anon_task` closure. If computing this goal depends on something
+        // not tracked by the cache key and from outside of this anon task, it
+        // must not be added to the global cache. Notably, this is the case for
+        // trait solver cycles participants.
         let ((final_entry, result), dep_node) =
             tcx.dep_graph.with_anon_task(tcx, dep_kinds::TraitSelect, || {
-                // When we encounter a coinductive cycle, we have to fetch the
-                // result of that cycle while we are still computing it. Because
-                // of this we continuously recompute the cycle until the result
-                // of the previous iteration is equal to the final result, at which
-                // point we are done.
                 for _ in 0..FIXPOINT_STEP_LIMIT {
-                    let result = prove_goal(self, inspect);
-                    let stack_entry = self.pop_stack();
-                    debug_assert_eq!(stack_entry.input, input);
-
-                    // If the current goal is not the root of a cycle, we are done.
-                    if stack_entry.has_been_used.is_empty() {
-                        return (stack_entry, result);
-                    }
-
-                    // If it is a cycle head, we have to keep trying to prove it until
-                    // we reach a fixpoint. We need to do so for all cycle heads,
-                    // not only for the root.
-                    //
-                    // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
-                    // for an example.
-
-                    // Start by clearing all provisional cache entries which depend on this
-                    // the current goal.
-                    Self::clear_dependent_provisional_results(
-                        &mut self.provisional_cache,
-                        self.stack.next_index(),
-                    );
-
-                    // Check whether we reached a fixpoint, either because the final result
-                    // is equal to the provisional result of the previous iteration, or because
-                    // this was only the root of either coinductive or inductive cycles, and the
-                    // final result is equal to the initial response for that case.
-                    let reached_fixpoint = if let Some(r) = stack_entry.provisional_result {
-                        r == result
-                    } else if stack_entry.has_been_used == HasBeenUsed::COINDUCTIVE_CYCLE {
-                        Self::response_no_constraints(tcx, input, Certainty::Yes) == result
-                    } else if stack_entry.has_been_used == HasBeenUsed::INDUCTIVE_CYCLE {
-                        Self::response_no_constraints(tcx, input, Certainty::overflow(false))
-                            == result
-                    } else {
-                        false
-                    };
-
-                    // If we did not reach a fixpoint, update the provisional result and reevaluate.
-                    if reached_fixpoint {
-                        return (stack_entry, result);
-                    } else {
-                        let depth = self.stack.push(StackEntry {
-                            has_been_used: HasBeenUsed::empty(),
-                            provisional_result: Some(result),
-                            ..stack_entry
-                        });
-                        debug_assert_eq!(self.provisional_cache[&input].stack_depth, Some(depth));
+                    match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) {
+                        StepResult::Done(final_entry, result) => return (final_entry, result),
+                        StepResult::HasChanged => {}
                     }
                 }
 
@@ -473,14 +389,13 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
         } else {
             self.provisional_cache.remove(&input);
             let reached_depth = final_entry.reached_depth.as_usize() - self.stack.len();
-            let cycle_participants = mem::take(&mut self.cycle_participants);
             // When encountering a cycle, both inductive and coinductive, we only
             // move the root into the global cache. We also store all other cycle
             // participants involved.
             //
             // We must not use the global cache entry of a root goal if a cycle
             // participant is on the stack. This is necessary to prevent unstable
-            // results. See the comment of `SearchGraph::cycle_participants` for
+            // results. See the comment of `StackEntry::cycle_participants` for
             // more details.
             self.global_cache(tcx).insert(
                 tcx,
@@ -488,15 +403,129 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
                 proof_tree,
                 reached_depth,
                 final_entry.encountered_overflow,
-                cycle_participants,
+                final_entry.cycle_participants,
                 dep_node,
                 result,
             )
         }
 
+        self.check_invariants();
+
         result
     }
 
+    /// Try to fetch a previously computed result from the global cache,
+    /// making sure to only do so if it would match the result of reevaluating
+    /// this goal.
+    fn lookup_global_cache(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        input: CanonicalInput<TyCtxt<'tcx>>,
+        available_depth: Limit,
+        inspect: &mut ProofTreeBuilder<TyCtxt<'tcx>>,
+    ) -> Option<QueryResult<TyCtxt<'tcx>>> {
+        let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self
+            .global_cache(tcx)
+            .get(tcx, input, self.stack.iter().map(|e| e.input), available_depth)?;
+
+        // If we're building a proof tree and the current cache entry does not
+        // contain a proof tree, we do not use the entry but instead recompute
+        // the goal. We simply overwrite the existing entry once we're done,
+        // caching the proof tree.
+        if !inspect.is_noop() {
+            if let Some(revisions) = proof_tree {
+                let kind = inspect::WipCanonicalGoalEvaluationKind::Interned { revisions };
+                inspect.goal_evaluation_kind(kind);
+            } else {
+                return None;
+            }
+        }
+
+        // Update the reached depth of the current goal to make sure
+        // its state is the same regardless of whether we've used the
+        // global cache or not.
+        let reached_depth = self.stack.next_index().plus(additional_depth);
+        if let Some(last) = self.stack.raw.last_mut() {
+            last.reached_depth = last.reached_depth.max(reached_depth);
+            last.encountered_overflow |= encountered_overflow;
+        }
+
+        Some(result)
+    }
+}
+
+enum StepResult<I: Interner> {
+    Done(StackEntry<I>, QueryResult<I>),
+    HasChanged,
+}
+
+impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
+    /// When we encounter a coinductive cycle, we have to fetch the
+    /// result of that cycle while we are still computing it. Because
+    /// of this we continuously recompute the cycle until the result
+    /// of the previous iteration is equal to the final result, at which
+    /// point we are done.
+    fn fixpoint_step_in_task<F>(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        input: CanonicalInput<TyCtxt<'tcx>>,
+        inspect: &mut ProofTreeBuilder<TyCtxt<'tcx>>,
+        prove_goal: &mut F,
+    ) -> StepResult<TyCtxt<'tcx>>
+    where
+        F: FnMut(&mut Self, &mut ProofTreeBuilder<TyCtxt<'tcx>>) -> QueryResult<TyCtxt<'tcx>>,
+    {
+        let result = prove_goal(self, inspect);
+        let stack_entry = self.pop_stack();
+        debug_assert_eq!(stack_entry.input, input);
+
+        // If the current goal is not the root of a cycle, we are done.
+        if stack_entry.has_been_used.is_empty() {
+            return StepResult::Done(stack_entry, result);
+        }
+
+        // If it is a cycle head, we have to keep trying to prove it until
+        // we reach a fixpoint. We need to do so for all cycle heads,
+        // not only for the root.
+        //
+        // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
+        // for an example.
+
+        // Start by clearing all provisional cache entries which depend on this
+        // the current goal.
+        Self::clear_dependent_provisional_results(
+            &mut self.provisional_cache,
+            self.stack.next_index(),
+        );
+
+        // Check whether we reached a fixpoint, either because the final result
+        // is equal to the provisional result of the previous iteration, or because
+        // this was only the root of either coinductive or inductive cycles, and the
+        // final result is equal to the initial response for that case.
+        let reached_fixpoint = if let Some(r) = stack_entry.provisional_result {
+            r == result
+        } else if stack_entry.has_been_used == HasBeenUsed::COINDUCTIVE_CYCLE {
+            Self::response_no_constraints(tcx, input, Certainty::Yes) == result
+        } else if stack_entry.has_been_used == HasBeenUsed::INDUCTIVE_CYCLE {
+            Self::response_no_constraints(tcx, input, Certainty::overflow(false)) == result
+        } else {
+            false
+        };
+
+        // If we did not reach a fixpoint, update the provisional result and reevaluate.
+        if reached_fixpoint {
+            StepResult::Done(stack_entry, result)
+        } else {
+            let depth = self.stack.push(StackEntry {
+                has_been_used: HasBeenUsed::empty(),
+                provisional_result: Some(result),
+                ..stack_entry
+            });
+            debug_assert_eq!(self.provisional_cache[&input].stack_depth, Some(depth));
+            StepResult::HasChanged
+        }
+    }
+
     fn response_no_constraints(
         tcx: TyCtxt<'tcx>,
         goal: CanonicalInput<TyCtxt<'tcx>>,
@@ -505,3 +534,77 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
         Ok(super::response_no_constraints_raw(tcx, goal.max_universe, goal.variables, certainty))
     }
 }
+
+impl<I: Interner> SearchGraph<I> {
+    #[allow(rustc::potential_query_instability)]
+    fn check_invariants(&self) {
+        if !cfg!(debug_assertions) {
+            return;
+        }
+
+        let SearchGraph { mode: _, stack, provisional_cache } = self;
+        if stack.is_empty() {
+            assert!(provisional_cache.is_empty());
+        }
+
+        for (depth, entry) in stack.iter_enumerated() {
+            let StackEntry {
+                input,
+                available_depth: _,
+                reached_depth: _,
+                non_root_cycle_participant,
+                encountered_overflow: _,
+                has_been_used,
+                ref cycle_participants,
+                provisional_result,
+            } = *entry;
+            let cache_entry = provisional_cache.get(&entry.input).unwrap();
+            assert_eq!(cache_entry.stack_depth, Some(depth));
+            if let Some(head) = non_root_cycle_participant {
+                assert!(head < depth);
+                assert!(cycle_participants.is_empty());
+                assert_ne!(stack[head].has_been_used, HasBeenUsed::empty());
+
+                let mut current_root = head;
+                while let Some(parent) = stack[current_root].non_root_cycle_participant {
+                    current_root = parent;
+                }
+                assert!(stack[current_root].cycle_participants.contains(&input));
+            }
+
+            if !cycle_participants.is_empty() {
+                assert!(provisional_result.is_some() || !has_been_used.is_empty());
+                for entry in stack.iter().take(depth.as_usize()) {
+                    assert_eq!(cycle_participants.get(&entry.input), None);
+                }
+            }
+        }
+
+        for (&input, entry) in &self.provisional_cache {
+            let ProvisionalCacheEntry { stack_depth, with_coinductive_stack, with_inductive_stack } =
+                entry;
+            assert!(
+                stack_depth.is_some()
+                    || with_coinductive_stack.is_some()
+                    || with_inductive_stack.is_some()
+            );
+
+            if let &Some(stack_depth) = stack_depth {
+                assert_eq!(stack[stack_depth].input, input);
+            }
+
+            let check_detached = |detached_entry: &DetachedEntry<I>| {
+                let DetachedEntry { head, result: _ } = *detached_entry;
+                assert_ne!(stack[head].has_been_used, HasBeenUsed::empty());
+            };
+
+            if let Some(with_coinductive_stack) = with_coinductive_stack {
+                check_detached(with_coinductive_stack);
+            }
+
+            if let Some(with_inductive_stack) = with_inductive_stack {
+                check_detached(with_inductive_stack);
+            }
+        }
+    }
+}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 52729ba1f84..a77d438e1f1 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -33,9 +33,6 @@ addr2line = { version = "0.21.0", optional = true, default-features = false }
 [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
 libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
 
-[target.'cfg(all(windows, target_env = "msvc"))'.dependencies]
-libc = { version = "0.2.153", default-features = false }
-
 [target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
 object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
 
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 37492e9efab..a1a8b2a3505 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -328,7 +328,7 @@ where
     fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         let prev_written = cursor.written();
 
-        Read::read_buf(&mut self.fill_buf()?, cursor.reborrow())?;
+        Read::read_buf(&mut self.remaining_slice(), cursor.reborrow())?;
 
         self.pos += (cursor.written() - prev_written) as u64;
 
@@ -352,17 +352,24 @@ where
     }
 
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
-        let n = buf.len();
-        Read::read_exact(&mut self.remaining_slice(), buf)?;
-        self.pos += n as u64;
-        Ok(())
+        let result = Read::read_exact(&mut self.remaining_slice(), buf);
+
+        match result {
+            Ok(_) => self.pos += buf.len() as u64,
+            // The only possible error condition is EOF, so place the cursor at "EOF"
+            Err(_) => self.pos = self.inner.as_ref().len() as u64,
+        }
+
+        result
     }
 
-    fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
-        let n = cursor.capacity();
-        Read::read_buf_exact(&mut self.remaining_slice(), cursor)?;
-        self.pos += n as u64;
-        Ok(())
+    fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        let prev_written = cursor.written();
+
+        let result = Read::read_buf_exact(&mut self.remaining_slice(), cursor.reborrow());
+        self.pos += (cursor.written() - prev_written) as u64;
+
+        result
     }
 
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 46f04c7cd39..a8a2e9413e1 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -287,6 +287,9 @@ impl Read for &[u8] {
     #[inline]
     fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
         if buf.len() > self.len() {
+            // `read_exact` makes no promise about the content of `buf` if it
+            // fails so don't bother about that.
+            *self = &self[self.len()..];
             return Err(io::Error::READ_EXACT_EOF);
         }
         let (a, b) = self.split_at(buf.len());
@@ -307,6 +310,9 @@ impl Read for &[u8] {
     #[inline]
     fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
         if cursor.capacity() > self.len() {
+            // Append everything we can to the cursor.
+            cursor.append(*self);
+            *self = &self[self.len()..];
             return Err(io::Error::READ_EXACT_EOF);
         }
         let (a, b) = self.split_at(cursor.capacity());
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 090a091b09a..a2c1c430863 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -653,6 +653,38 @@ fn test_take_wrong_length() {
     let _ = reader.read(&mut buffer[..]);
 }
 
+#[test]
+fn slice_read_exact_eof() {
+    let slice = &b"123456"[..];
+
+    let mut r = slice;
+    assert!(r.read_exact(&mut [0; 10]).is_err());
+    assert!(r.is_empty());
+
+    let mut r = slice;
+    let buf = &mut [0; 10];
+    let mut buf = BorrowedBuf::from(buf.as_mut_slice());
+    assert!(r.read_buf_exact(buf.unfilled()).is_err());
+    assert!(r.is_empty());
+    assert_eq!(buf.filled(), b"123456");
+}
+
+#[test]
+fn cursor_read_exact_eof() {
+    let slice = Cursor::new(b"123456");
+
+    let mut r = slice.clone();
+    assert!(r.read_exact(&mut [0; 10]).is_err());
+    assert!(r.is_empty());
+
+    let mut r = slice;
+    let buf = &mut [0; 10];
+    let mut buf = BorrowedBuf::from(buf.as_mut_slice());
+    assert!(r.read_buf_exact(buf.unfilled()).is_err());
+    assert!(r.is_empty());
+    assert_eq!(buf.filled(), b"123456");
+}
+
 #[bench]
 fn bench_take_read(b: &mut test::Bencher) {
     b.iter(|| {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 27b46b46204..949c543a264 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -435,6 +435,7 @@ extern crate alloc as alloc_crate;
 // so include it here even if it's unused.
 #[doc(masked)]
 #[allow(unused_extern_crates)]
+#[cfg(not(all(windows, target_env = "msvc")))]
 extern crate libc;
 
 // We always need an unwinder currently for backtraces
diff --git a/library/std/src/os/raw/tests.rs b/library/std/src/os/raw/tests.rs
index e7bb7d7e73e..f41a22e1bcc 100644
--- a/library/std/src/os/raw/tests.rs
+++ b/library/std/src/os/raw/tests.rs
@@ -1,3 +1,5 @@
+#![cfg(not(all(windows, target_env = "msvc")))]
+
 use crate::any::TypeId;
 
 macro_rules! ok {
diff --git a/library/std/src/sys/pal/hermit/net.rs b/library/std/src/sys/pal/hermit/net.rs
index 23ac71cb9f2..00dbca86a4b 100644
--- a/library/std/src/sys/pal/hermit/net.rs
+++ b/library/std/src/sys/pal/hermit/net.rs
@@ -175,23 +175,12 @@ impl Socket {
     }
 
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        let mut size: isize = 0;
-
-        for i in bufs.iter_mut() {
-            let ret: isize =
-                cvt(unsafe { netc::read(self.0.as_raw_fd(), i.as_mut_ptr(), i.len()) })?;
-
-            if ret != 0 {
-                size += ret;
-            }
-        }
-
-        Ok(size.try_into().unwrap())
+        crate::io::default_read_vectored(|b| self.read(b), bufs)
     }
 
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        true
+        false
     }
 
     fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<(usize, SocketAddr)> {
@@ -225,17 +214,11 @@ impl Socket {
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let mut size: isize = 0;
-
-        for i in bufs.iter() {
-            size += cvt(unsafe { netc::write(self.0.as_raw_fd(), i.as_ptr(), i.len()) })?;
-        }
-
-        Ok(size.try_into().unwrap())
+        crate::io::default_write_vectored(|b| self.write(b), bufs)
     }
 
     pub fn is_write_vectored(&self) -> bool {
-        true
+        false
     }
 
     pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> {
diff --git a/src/doc/book b/src/doc/book
-Subproject bebcf527e67755a989a1739b7cfaa8f0e6b3004
+Subproject 5e9051f71638aa941cd5dda465e25c61cde9594
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 17842ebb050f62e40a4618edeb8e8ee86e75870
+Subproject dd962bb82865a5284f2404e5234f1e3222b9c02
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 51817951d0d213a0011f82b62aae02c3b3f2472
+Subproject e356977fceaa8591c762312d8d446769166d4b3
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 229ad13b64d919b12e548d560f06d88963b25cd
+Subproject 20482893d1a502df72f76762c97aed88854cdf8
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 2d1947ff34d50ca46dfe242ad75531a4c429bb5
+Subproject b6d4a4940bab85cc91eec70cc2e3096dd48da62
diff --git a/tests/incremental/foreign.rs b/tests/incremental/foreign.rs
index cb040fe1296..1af203e9b77 100644
--- a/tests/incremental/foreign.rs
+++ b/tests/incremental/foreign.rs
@@ -1,38 +1,21 @@
 // Test what happens we save incremental compilation state that makes
 // use of foreign items. This used to ICE (#34991).
-//@ ignore-sgx no libc
-
 //@ revisions: rpass1
 
-#![feature(rustc_private)]
-
-extern crate libc;
-
 use std::ffi::CString;
 
 mod mlibc {
-    use libc::{c_char, c_long, c_longlong};
-
     extern "C" {
-        pub fn atol(x: *const c_char) -> c_long;
-        pub fn atoll(x: *const c_char) -> c_longlong;
+        // strlen is provided either by an external library or compiler-builtins as a fallback
+        pub fn strlen(x: *const std::ffi::c_char) -> usize;
     }
 }
 
-fn atol(s: String) -> isize {
-    let c = CString::new(s).unwrap();
-    unsafe { mlibc::atol(c.as_ptr()) as isize }
-}
-
-fn atoll(s: String) -> i64 {
+fn strlen(s: String) -> usize {
     let c = CString::new(s).unwrap();
-    unsafe { mlibc::atoll(c.as_ptr()) as i64 }
+    unsafe { mlibc::strlen(c.as_ptr()) }
 }
 
 pub fn main() {
-    assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
-    assert_eq!(
-        (atoll("11111111111111111".to_string()) * 10),
-        atoll("111111111111111110".to_string())
-    );
+    assert_eq!(strlen("1024".to_string()), strlen("2048".to_string()));
 }
diff --git a/tests/pretty/issue-4264.pp b/tests/pretty/issue-4264.pp
index af64260d020..4d43db5716e 100644
--- a/tests/pretty/issue-4264.pp
+++ b/tests/pretty/issue-4264.pp
@@ -11,15 +11,15 @@ extern crate std;
 fn foo(_: [i32; (3 as usize)]) ({ } as ())
 
 fn bar() ({
-        const FOO: usize = ((5 as usize) - (4 as usize) as usize);
-        let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]);
+    const FOO: usize = ((5 as usize) - (4 as usize) as usize);
+    let _: [(); (FOO as usize)] = ([(() as ())] as [(); 1]);
 
-        let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]);
+    let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]);
 
-        let _ =
-            (((&([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3]) as
-                        &[i32; 3]) as *const _ as *const [i32; 3]) as
-                *const [i32; (3 as usize)] as *const [i32; 3]);
+    let _ =
+        (((&([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3]) as &[i32; 3])
+                as *const _ as *const [i32; 3]) as *const [i32; (3 as usize)]
+            as *const [i32; 3]);
 
 
 
@@ -29,17 +29,17 @@ fn bar() ({
 
 
 
-        ({
-                let res =
-                    ((::alloc::fmt::format as
-                            for<'a> fn(Arguments<'a>) -> String {format})(((format_arguments::new_const
-                                as
-                                fn(&[&'static str]) -> Arguments<'_> {Arguments::<'_>::new_const})((&([("test"
-                                            as &str)] as [&str; 1]) as &[&str; 1])) as Arguments<'_>))
-                        as String);
-                (res as String)
-            } as String);
-    } as ())
+    ({
+        let res =
+            ((::alloc::fmt::format as
+                    for<'a> fn(Arguments<'a>) -> String {format})(((format_arguments::new_const
+                        as
+                        fn(&[&'static str]) -> Arguments<'_> {Arguments::<'_>::new_const})((&([("test"
+                                    as &str)] as [&str; 1]) as &[&str; 1])) as Arguments<'_>))
+                as String);
+        (res as String)
+    } as String);
+} as ())
 type Foo = [i32; (3 as usize)];
 struct Bar {
     x: [i32; (3 as usize)],
@@ -48,9 +48,9 @@ struct TupleBar([i32; (4 as usize)]);
 enum Baz { BazVariant([i32; (5 as usize)]), }
 fn id<T>(x: T) -> T ({ (x as T) } as T)
 fn use_id() ({
-        let _ =
-            ((id::<[i32; (3 as usize)]> as
-                    fn([i32; 3]) -> [i32; 3] {id::<[i32; 3]>})(([(1 as i32),
-                        (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]);
-    } as ())
+    let _ =
+        ((id::<[i32; (3 as usize)]> as
+                fn([i32; 3]) -> [i32; 3] {id::<[i32; 3]>})(([(1 as i32),
+                    (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]);
+} as ())
 fn main() ({ } as ())
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
index 5830ef033d3..e518579b906 100644
--- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
+++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
@@ -1,10 +1,7 @@
 #![crate_type = "staticlib"]
 #![feature(c_variadic)]
-#![feature(rustc_private)]
 
-extern crate libc;
-
-use libc::{c_char, c_double, c_int, c_long, c_longlong};
+use std::ffi::{c_char, c_double, c_int, c_long, c_longlong};
 use std::ffi::VaList;
 use std::ffi::{CString, CStr};
 
diff --git a/tests/run-make/link-path-order/main.rs b/tests/run-make/link-path-order/main.rs
index 8024e343d19..20a517dcda9 100644
--- a/tests/run-make/link-path-order/main.rs
+++ b/tests/run-make/link-path-order/main.rs
@@ -1,10 +1,8 @@
-#![feature(rustc_private)]
-
-extern crate libc;
+use std::ffi::c_int;
 
 #[link(name = "foo", kind = "static")]
 extern "C" {
-    fn should_return_one() -> libc::c_int;
+    fn should_return_one() -> c_int;
 }
 
 fn main() {
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr
index 45d571f435c..f4b6947ccd9 100644
--- a/tests/ui/attributes/rustc_confusables_std_cases.stderr
+++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr
@@ -26,6 +26,14 @@ error[E0599]: no method named `push` found for struct `VecDeque` in the current
 LL |     x.push(1);
    |       ^^^^ method not found in `VecDeque<_>`
    |
+note: there's an earlier shadowed binding `x` of type `Vec<_>` that has method `push` available
+  --> $DIR/rustc_confusables_std_cases.rs:8:9
+   |
+LL |     let mut x = Vec::new();
+   |         ^^^^^ `x` of type `Vec<_>` that has method `push` defined earlier here
+...
+LL |     let mut x = VecDeque::new();
+   |         ----- earlier `x` shadowed here with type `VecDeque`
 help: you might have meant to use `push_back`
    |
 LL |     x.push_back(1);
diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr
index 96f51a4e7a2..b62c67d9a9d 100644
--- a/tests/ui/derives/deriving-with-repr-packed-2.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr
@@ -10,6 +10,14 @@ LL | struct NonCopy;
 LL |     _ = x.clone();
    |           ^^^^^ method cannot be called on `Foo<NonCopy>` due to unsatisfied trait bounds
    |
+note: there's an earlier shadowed binding `x` of type `Foo<u32>` that has method `clone` available
+  --> $DIR/deriving-with-repr-packed-2.rs:13:9
+   |
+LL |     let x: Foo<u32> = Foo(1, 2, 3);
+   |         ^ `x` of type `Foo<u32>` that has method `clone` defined earlier here
+...
+LL |     let x: Foo<NonCopy> = Foo(NonCopy, NonCopy, NonCopy);
+   |         - earlier `x` shadowed here with type `Foo<NonCopy>`
 note: the following trait bounds were not satisfied:
       `NonCopy: Clone`
       `NonCopy: Copy`
diff --git a/tests/ui/env-null-vars.rs b/tests/ui/env-null-vars.rs
index bb86fd353c4..24d783553d1 100644
--- a/tests/ui/env-null-vars.rs
+++ b/tests/ui/env-null-vars.rs
@@ -1,21 +1,15 @@
+// Ensure that env::vars() does not panic if environ is null.
+// Regression test for rust-lang/rust#53200
 //@ run-pass
 
-#![allow(unused_imports)]
-
-//@ ignore-windows
-
-// issue-53200
-
 #![feature(rustc_private)]
-extern crate libc;
-
-use std::env;
 
 // FIXME: more platforms?
 #[cfg(target_os = "linux")]
 fn main() {
+    extern crate libc;
     unsafe { libc::clearenv(); }
-    assert_eq!(env::vars().count(), 0);
+    assert_eq!(std::env::vars().count(), 0);
 }
 
 #[cfg(not(target_os = "linux"))]
diff --git a/tests/ui/error-codes/E0259.rs b/tests/ui/error-codes/E0259.rs
index e7e94d58635..78e56deccb4 100644
--- a/tests/ui/error-codes/E0259.rs
+++ b/tests/ui/error-codes/E0259.rs
@@ -1,8 +1,8 @@
-#![feature(rustc_private)]
+#![feature(test)]
 
 extern crate alloc;
 
-extern crate libc as alloc;
+extern crate test as alloc;
 //~^ ERROR E0259
 
 fn main() {}
diff --git a/tests/ui/error-codes/E0259.stderr b/tests/ui/error-codes/E0259.stderr
index 6e086268fc6..975d1a161a0 100644
--- a/tests/ui/error-codes/E0259.stderr
+++ b/tests/ui/error-codes/E0259.stderr
@@ -4,13 +4,13 @@ error[E0259]: the name `alloc` is defined multiple times
 LL | extern crate alloc;
    | ------------------- previous import of the extern crate `alloc` here
 LL |
-LL | extern crate libc as alloc;
+LL | extern crate test as alloc;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `alloc` reimported here
    |
    = note: `alloc` must be defined only once in the type namespace of this module
 help: you can use `as` to change the binding name of the import
    |
-LL | extern crate libc as other_alloc;
+LL | extern crate test as other_alloc;
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/feature-gates/rustc-private.rs b/tests/ui/feature-gates/rustc-private.rs
index 7b8944bb0a0..aa44f790c8a 100644
--- a/tests/ui/feature-gates/rustc-private.rs
+++ b/tests/ui/feature-gates/rustc-private.rs
@@ -1,5 +1,5 @@
 // gate-test-rustc_private
 
-extern crate libc; //~ ERROR  use of unstable library feature 'rustc_private'
+extern crate cfg_if; //~ ERROR  use of unstable library feature 'rustc_private'
 
 fn main() {}
diff --git a/tests/ui/feature-gates/rustc-private.stderr b/tests/ui/feature-gates/rustc-private.stderr
index 03397cba763..96cc98619fd 100644
--- a/tests/ui/feature-gates/rustc-private.stderr
+++ b/tests/ui/feature-gates/rustc-private.stderr
@@ -1,8 +1,8 @@
 error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/rustc-private.rs:3:1
    |
-LL | extern crate libc;
-   | ^^^^^^^^^^^^^^^^^^
+LL | extern crate cfg_if;
+   | ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
diff --git a/tests/ui/foreign/foreign-fn-linkname.rs b/tests/ui/foreign/foreign-fn-linkname.rs
index 47edf6fc7bb..7ced34e73fa 100644
--- a/tests/ui/foreign/foreign-fn-linkname.rs
+++ b/tests/ui/foreign/foreign-fn-linkname.rs
@@ -1,20 +1,14 @@
 //@ run-pass
 //@ ignore-sgx no libc
 
-// Ensure no false positive on "unused extern crate" lint
-#![deny(unused_extern_crates)]
-
-#![feature(rustc_private)]
-
-extern crate libc;
 use std::ffi::CString;
 
 mod mlibc {
-    use libc::{c_char, size_t};
+    use std::ffi::c_char;
 
     extern "C" {
         #[link_name = "strlen"]
-        pub fn my_strlen(str: *const c_char) -> size_t;
+        pub fn my_strlen(str: *const c_char) -> usize;
     }
 }
 
diff --git a/tests/ui/foreign/foreign2.rs b/tests/ui/foreign/foreign2.rs
index eb24df35033..178a04255cc 100644
--- a/tests/ui/foreign/foreign2.rs
+++ b/tests/ui/foreign/foreign2.rs
@@ -1,9 +1,8 @@
 //@ run-pass
-#![allow(dead_code)]
 //@ pretty-expanded FIXME #23616
-#![feature(rustc_private)]
 
-extern crate libc;
+#![allow(dead_code)]
+#![feature(rustc_private)]
 
 mod bar {
     extern "C" {}
@@ -13,14 +12,37 @@ mod zed {
     extern "C" {}
 }
 
+#[cfg(not(windows))]
 mod mlibc {
-    use libc::{c_int, c_void, size_t, ssize_t};
+    extern crate libc;
+    use self::libc::{c_int, c_void, size_t, ssize_t};
 
     extern "C" {
         pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t;
     }
 }
 
+#[cfg(windows)]
+mod mlibc {
+    #![allow(non_snake_case)]
+
+    use std::ffi::c_void;
+
+    pub type BOOL = i32;
+    pub type HANDLE = *mut c_void;
+
+    #[link(name = "ntdll")]
+    extern "system" {
+        pub fn WriteFile(
+            hfile: HANDLE,
+            lpbuffer: *const u8,
+            nnumberofbytestowrite: u32,
+            lpnumberofbyteswritten: *mut u32,
+            lpoverlapped: *mut c_void,
+        ) -> BOOL;
+    }
+}
+
 mod baz {
     extern "C" {}
 }
diff --git a/tests/ui/imports/issue-37887.rs b/tests/ui/imports/issue-37887.rs
index 58f0c6b651a..919f46d34c6 100644
--- a/tests/ui/imports/issue-37887.rs
+++ b/tests/ui/imports/issue-37887.rs
@@ -1,4 +1,4 @@
 fn main() {
-    extern crate libc; //~ ERROR use of unstable
-    use libc::*; //~ ERROR unresolved import
+    extern crate test; //~ ERROR use of unstable
+    use test::*; //~ ERROR unresolved import
 }
diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr
index 6117fd21af1..e7792ac0d15 100644
--- a/tests/ui/imports/issue-37887.stderr
+++ b/tests/ui/imports/issue-37887.stderr
@@ -1,19 +1,19 @@
-error[E0432]: unresolved import `libc`
+error[E0432]: unresolved import `test`
   --> $DIR/issue-37887.rs:3:9
    |
-LL |     use libc::*;
-   |         ^^^^ maybe a missing crate `libc`?
+LL |     use test::*;
+   |         ^^^^ maybe a missing crate `test`?
    |
-   = help: consider adding `extern crate libc` to use the `libc` crate
+   = help: consider adding `extern crate test` to use the `test` crate
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+error[E0658]: use of unstable library feature 'test'
   --> $DIR/issue-37887.rs:2:5
    |
-LL |     extern crate libc;
+LL |     extern crate test;
    |     ^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
-   = help: add `#![feature(rustc_private)]` to the crate attributes to enable
+   = note: see issue #50297 <https://github.com/rust-lang/rust/issues/50297> for more information
+   = help: add `#![feature(test)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/lint/unnecessary-extern-crate.rs b/tests/ui/lint/unnecessary-extern-crate.rs
index 6ca3b96758f..7f97a4c469e 100644
--- a/tests/ui/lint/unnecessary-extern-crate.rs
+++ b/tests/ui/lint/unnecessary-extern-crate.rs
@@ -1,12 +1,12 @@
 //@ edition:2018
 
 #![deny(unused_extern_crates)]
-#![feature(test, rustc_private)]
+#![feature(test)]
 
-extern crate libc;
+extern crate core;
 //~^ ERROR unused extern crate
 //~| HELP remove
-extern crate libc as x;
+extern crate core as x;
 //~^ ERROR unused extern crate
 //~| HELP remove
 
@@ -28,11 +28,11 @@ mod foo {
 
     pub(super) extern crate alloc as d;
 
-    extern crate libc;
+    extern crate core;
     //~^ ERROR unused extern crate
     //~| HELP remove
 
-    extern crate libc as x;
+    extern crate core as x;
     //~^ ERROR unused extern crate
     //~| HELP remove
 
@@ -41,11 +41,11 @@ mod foo {
     pub extern crate test as y;
 
     mod bar {
-        extern crate libc;
+        extern crate core;
         //~^ ERROR unused extern crate
         //~| HELP remove
 
-        extern crate libc as x;
+        extern crate core as x;
         //~^ ERROR unused extern crate
         //~| HELP remove
 
diff --git a/tests/ui/lint/unnecessary-extern-crate.stderr b/tests/ui/lint/unnecessary-extern-crate.stderr
index 14ba9d052f4..1fa4aa9c9a9 100644
--- a/tests/ui/lint/unnecessary-extern-crate.stderr
+++ b/tests/ui/lint/unnecessary-extern-crate.stderr
@@ -1,7 +1,7 @@
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:6:1
    |
-LL | extern crate libc;
+LL | extern crate core;
    | ^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: the lint level is defined here
@@ -13,31 +13,31 @@ LL | #![deny(unused_extern_crates)]
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:9:1
    |
-LL | extern crate libc as x;
+LL | extern crate core as x;
    | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:31:5
    |
-LL |     extern crate libc;
+LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:35:5
    |
-LL |     extern crate libc as x;
+LL |     extern crate core as x;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:44:9
    |
-LL |         extern crate libc;
+LL |         extern crate core;
    |         ^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: unused extern crate
   --> $DIR/unnecessary-extern-crate.rs:48:9
    |
-LL |         extern crate libc as x;
+LL |         extern crate core as x;
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/match/issue-82392.stdout b/tests/ui/match/issue-82392.stdout
index 8a23d906757..8949611ac12 100644
--- a/tests/ui/match/issue-82392.stdout
+++ b/tests/ui/match/issue-82392.stdout
@@ -7,10 +7,10 @@ extern crate std;
 //@ check-pass
 
 fn main() ({
-        (if (true as bool)
-                ({ } as
-                    ()) else if (let Some(a) =
-                       ((Some as
-                               fn(i32) -> Option<i32> {Option::<i32>::Some})((3 as i32)) as
-                           Option<i32>) as bool) ({ } as ()) as ())
-               } as ())
+    (if (true as bool)
+            ({ } as
+                ()) else if (let Some(a) =
+                   ((Some as
+                           fn(i32) -> Option<i32> {Option::<i32>::Some})((3 as i32)) as
+                       Option<i32>) as bool) ({ } as ()) as ())
+           } as ())
diff --git a/tests/ui/meta/no_std-extern-libc.rs b/tests/ui/meta/no_std-extern-libc.rs
index 919caf9428f..8b89e14382d 100644
--- a/tests/ui/meta/no_std-extern-libc.rs
+++ b/tests/ui/meta/no_std-extern-libc.rs
@@ -1,5 +1,6 @@
 // Test that `download-rustc` doesn't put duplicate copies of libc in the sysroot.
 //@ check-pass
+//@ ignore-windows doesn't necessarily have the libc crate
 #![crate_type = "lib"]
 #![no_std]
 #![feature(rustc_private)]
diff --git a/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.rs b/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.rs
new file mode 100644
index 00000000000..a08bbf1fdbe
--- /dev/null
+++ b/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x = Some(3);
+    let y = vec![1, 2];
+    if let Some(y) = x {
+        y.push(y); //~ ERROR E0599
+    }
+}
diff --git a/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.stderr b/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.stderr
new file mode 100644
index 00000000000..aecad201c7b
--- /dev/null
+++ b/tests/ui/methods/issues/account-for-shadowed-bindings-issue-123558.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `push` found for type `{integer}` in the current scope
+  --> $DIR/account-for-shadowed-bindings-issue-123558.rs:5:11
+   |
+LL |         y.push(y);
+   |           ^^^^ method not found in `{integer}`
+   |
+note: there's an earlier shadowed binding `y` of type `Vec<{integer}>` that has method `push` available
+  --> $DIR/account-for-shadowed-bindings-issue-123558.rs:3:9
+   |
+LL |     let y = vec![1, 2];
+   |         ^ `y` of type `Vec<{integer}>` that has method `push` defined earlier here
+LL |     if let Some(y) = x {
+   |                 - earlier `y` shadowed here with type `{integer}`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/process/no-stdio.rs b/tests/ui/process/no-stdio.rs
index 05b1e52b799..8eebf6dbc7d 100644
--- a/tests/ui/process/no-stdio.rs
+++ b/tests/ui/process/no-stdio.rs
@@ -5,11 +5,13 @@
 
 #![feature(rustc_private)]
 
+#[cfg(unix)]
 extern crate libc;
 
-use std::process::{Command, Stdio};
 use std::env;
+use std::ffi::c_int;
 use std::io::{self, Read, Write};
+use std::process::{Command, Stdio};
 
 #[cfg(unix)]
 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
@@ -36,14 +38,14 @@ unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
 }
 
 #[cfg(unix)]
-fn assert_fd_is_valid(fd: libc::c_int) {
+fn assert_fd_is_valid(fd: c_int) {
     if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 } {
         panic!("file descriptor {} is not valid: {}", fd, io::Error::last_os_error());
     }
 }
 
 #[cfg(windows)]
-fn assert_fd_is_valid(_fd: libc::c_int) {}
+fn assert_fd_is_valid(_fd: c_int) {}
 
 #[cfg(windows)]
 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
diff --git a/tests/ui/runtime/on-broken-pipe/error.rs b/tests/ui/runtime/on-broken-pipe/error.rs
index ab2036c2f41..0a020873df0 100644
--- a/tests/ui/runtime/on-broken-pipe/error.rs
+++ b/tests/ui/runtime/on-broken-pipe/error.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 //@ aux-build:sigpipe-utils.rs
 //@ compile-flags: -Zon-broken-pipe=error
+//@ only-unix because SIGPIPE is a unix thing
 
 fn main() {
     extern crate sigpipe_utils;
diff --git a/tests/ui/runtime/on-broken-pipe/inherit.rs b/tests/ui/runtime/on-broken-pipe/inherit.rs
index 64909b73528..f3c8140eaae 100644
--- a/tests/ui/runtime/on-broken-pipe/inherit.rs
+++ b/tests/ui/runtime/on-broken-pipe/inherit.rs
@@ -4,6 +4,7 @@
 //@ aux-bin: assert-inherit-sig_ign.rs
 //@ run-pass
 //@ compile-flags: -Zon-broken-pipe=kill
+//@ only-unix because SIGPIPE is a unix thing
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/runtime/on-broken-pipe/kill.rs b/tests/ui/runtime/on-broken-pipe/kill.rs
index 5dace6f1c6f..748e53ffcdb 100644
--- a/tests/ui/runtime/on-broken-pipe/kill.rs
+++ b/tests/ui/runtime/on-broken-pipe/kill.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 //@ aux-build:sigpipe-utils.rs
 //@ compile-flags: -Zon-broken-pipe=kill
+//@ only-unix because SIGPIPE is a unix thing
 
 fn main() {
     extern crate sigpipe_utils;
diff --git a/tests/ui/runtime/on-broken-pipe/not-used.rs b/tests/ui/runtime/on-broken-pipe/not-used.rs
index e31236f2b3d..22a26047874 100644
--- a/tests/ui/runtime/on-broken-pipe/not-used.rs
+++ b/tests/ui/runtime/on-broken-pipe/not-used.rs
@@ -1,5 +1,6 @@
 //@ run-pass
 //@ aux-build:sigpipe-utils.rs
+//@ only-unix because SIGPIPE is a unix thing
 
 fn main() {
     extern crate sigpipe_utils;
diff --git a/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs
index c1731200038..c40590ad87f 100644
--- a/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs
+++ b/tests/ui/runtime/on-broken-pipe/with-rustc_main.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 //@ aux-build:sigpipe-utils.rs
 //@ compile-flags: -Zon-broken-pipe=kill
+//@ only-unix because SIGPIPE is a unix thing
 
 #![feature(rustc_attrs)]
 
diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs
index ab2b50b293c..a62398df8b8 100644
--- a/tests/ui/runtime/out-of-stack.rs
+++ b/tests/ui/runtime/out-of-stack.rs
@@ -8,21 +8,16 @@
 //@ ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
 //@ ignore-nto no stack overflow handler used (no alternate stack available)
 
-#![feature(core_intrinsics)]
 #![feature(rustc_private)]
 
 #[cfg(unix)]
 extern crate libc;
 
 use std::env;
+use std::hint::black_box;
 use std::process::Command;
 use std::thread;
 
-// Inlining to avoid llvm turning the recursive functions into tail calls,
-// which doesn't consume stack.
-#[inline(always)]
-pub fn black_box<T>(dummy: T) { std::intrinsics::black_box(dummy); }
-
 fn silent_recurse() {
     let buf = [0u8; 1000];
     black_box(buf);
diff --git a/tests/ui/runtime/stdout-during-shutdown.rs b/tests/ui/runtime/stdout-during-shutdown-unix.rs
index 8549f5d8eb6..8e0f1d371ae 100644
--- a/tests/ui/runtime/stdout-during-shutdown.rs
+++ b/tests/ui/runtime/stdout-during-shutdown-unix.rs
@@ -1,6 +1,7 @@
 //@ run-pass
 //@ check-run-results
 //@ ignore-emscripten
+//@ only-unix
 
 // Emscripten doesn't flush its own stdout buffers on exit, which would fail
 // this test. So this test is disabled on this platform.
diff --git a/tests/ui/runtime/stdout-during-shutdown.run.stdout b/tests/ui/runtime/stdout-during-shutdown-unix.run.stdout
index 30f51a3fba5..30f51a3fba5 100644
--- a/tests/ui/runtime/stdout-during-shutdown.run.stdout
+++ b/tests/ui/runtime/stdout-during-shutdown-unix.run.stdout
diff --git a/tests/ui/runtime/stdout-during-shutdown-windows.rs b/tests/ui/runtime/stdout-during-shutdown-windows.rs
new file mode 100644
index 00000000000..4644965b154
--- /dev/null
+++ b/tests/ui/runtime/stdout-during-shutdown-windows.rs
@@ -0,0 +1,20 @@
+//@ run-pass
+//@ check-run-results
+//@ only-windows
+
+struct Bye;
+
+impl Drop for Bye {
+    fn drop(&mut self) {
+        print!(", world!");
+    }
+}
+
+fn main() {
+    thread_local!{
+        static BYE: Bye = Bye;
+    }
+    BYE.with(|_| {
+        print!("hello");
+    });
+}
diff --git a/tests/ui/runtime/stdout-during-shutdown-windows.run.stdout b/tests/ui/runtime/stdout-during-shutdown-windows.run.stdout
new file mode 100644
index 00000000000..30f51a3fba5
--- /dev/null
+++ b/tests/ui/runtime/stdout-during-shutdown-windows.run.stdout
@@ -0,0 +1 @@
+hello, world!
\ No newline at end of file
diff --git a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
index 8df0613695b..99f8dbd9a6c 100644
--- a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
+++ b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr
@@ -25,8 +25,8 @@ LL +     let str::as_bytes;
    |
 
 error[E0533]: expected unit struct, unit variant or constant, found associated function `str<{
-                      fn str() { let (/*ERROR*/); }
-                  }, T>::as_bytes`
+                  fn str() { let (/*ERROR*/); }
+              }, T>::as_bytes`
   --> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:9
    |
 LL |     let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes;
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
index 7eea81ce03c..920f8add507 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
@@ -1,3 +1,4 @@
+//@ revisions: with without
 //@ compile-flags: -Znext-solver
 #![feature(rustc_attrs)]
 
@@ -56,6 +57,7 @@ where
     X: IncompleteGuidance<u32, i8>,
     X: IncompleteGuidance<u32, i16>,
 {
+    #[cfg(with)]
     impls_trait::<B<X>, _, _, _>(); // entering the cycle from `B` works
 
     // entering the cycle from `A` fails, but would work if we were to use the cache
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr
index ffa3f29e4bd..a81229e5e35 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.with.stderr
@@ -1,12 +1,12 @@
 error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
-  --> $DIR/incompleteness-unstable-result.rs:63:19
+  --> $DIR/incompleteness-unstable-result.rs:65:19
    |
 LL |     impls_trait::<A<X>, _, _, _>();
    |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
    |
    = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
 note: required for `A<X>` to implement `Trait<_, _, _>`
-  --> $DIR/incompleteness-unstable-result.rs:32:50
+  --> $DIR/incompleteness-unstable-result.rs:33:50
    |
 LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
    |                                                  ^^^^^^^^^^^^^^     ^^^^
@@ -16,7 +16,7 @@ LL |     A<T>: Trait<U, D, V>,
    = note: 8 redundant requirements hidden
    = note: required for `A<X>` to implement `Trait<_, _, _>`
 note: required by a bound in `impls_trait`
-  --> $DIR/incompleteness-unstable-result.rs:51:28
+  --> $DIR/incompleteness-unstable-result.rs:52:28
    |
 LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
    |                            ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr
new file mode 100644
index 00000000000..a81229e5e35
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.without.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
+  --> $DIR/incompleteness-unstable-result.rs:65:19
+   |
+LL |     impls_trait::<A<X>, _, _, _>();
+   |                   ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
+   |
+   = help: the trait `Trait<U, V, D>` is implemented for `A<T>`
+note: required for `A<X>` to implement `Trait<_, _, _>`
+  --> $DIR/incompleteness-unstable-result.rs:33:50
+   |
+LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
+   |                                                  ^^^^^^^^^^^^^^     ^^^^
+...
+LL |     A<T>: Trait<U, D, V>,
+   |           -------------- unsatisfied trait bound introduced here
+   = note: 8 redundant requirements hidden
+   = note: required for `A<X>` to implement `Trait<_, _, _>`
+note: required by a bound in `impls_trait`
+  --> $DIR/incompleteness-unstable-result.rs:52:28
+   |
+LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
+   |                            ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout
index e643dba1245..b541cbeb227 100644
--- a/tests/ui/type-alias-impl-trait/issue-60662.stdout
+++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout
@@ -10,5 +10,5 @@ extern crate std;
 trait Animal { }
 
 fn main() {
-        type ServeFut = /*impl Trait*/;
-    }
+    type ServeFut = /*impl Trait*/;
+}
diff --git a/tests/ui/unpretty/bad-literal.stdout b/tests/ui/unpretty/bad-literal.stdout
index 07ecb99dccc..c5272711d6e 100644
--- a/tests/ui/unpretty/bad-literal.stdout
+++ b/tests/ui/unpretty/bad-literal.stdout
@@ -7,5 +7,5 @@ extern crate std;
 
 // In #100948 this caused an ICE with -Zunpretty=hir.
 fn main() {
-        <bad-literal>;
-    }
+    <bad-literal>;
+}
diff --git a/tests/ui/unpretty/box.stdout b/tests/ui/unpretty/box.stdout
index 0fd51edea24..e3b9b9ac207 100644
--- a/tests/ui/unpretty/box.stdout
+++ b/tests/ui/unpretty/box.stdout
@@ -8,7 +8,7 @@ use ::std::prelude::rust_2015::*;
 extern crate std;
 
 fn main() {
-        let _ =
-            #[rustc_box]
-            Box::new(1);
-    }
+    let _ =
+        #[rustc_box]
+        Box::new(1);
+}
diff --git a/tests/ui/unpretty/flattened-format-args.stdout b/tests/ui/unpretty/flattened-format-args.stdout
index 275fa104e66..2de1cdd96b5 100644
--- a/tests/ui/unpretty/flattened-format-args.stdout
+++ b/tests/ui/unpretty/flattened-format-args.stdout
@@ -6,10 +6,10 @@ extern crate std;
 //@ check-pass
 
 fn main() {
-        let x = 1;
-        // Should flatten to println!("a 123 b {x} xyz\n"):
-        {
-                ::std::io::_print(format_arguments::new_v1(&["a 123 b ",
-                                    " xyz\n"], &[format_argument::new_display(&x)]));
-            };
-    }
+    let x = 1;
+    // Should flatten to println!("a 123 b {x} xyz\n"):
+    {
+        ::std::io::_print(format_arguments::new_v1(&["a 123 b ", " xyz\n"],
+                &[format_argument::new_display(&x)]));
+    };
+}
diff --git a/tests/ui/unpretty/let-else-hir.stdout b/tests/ui/unpretty/let-else-hir.stdout
index ed55f293876..a2ffa5de567 100644
--- a/tests/ui/unpretty/let-else-hir.stdout
+++ b/tests/ui/unpretty/let-else-hir.stdout
@@ -9,10 +9,10 @@ extern crate std;
 
 fn foo(x:
         Option<u32>) {
-        let Some(_) = x else
-            {
+    let Some(_) = x else
+        {
 
-            { ::std::rt::begin_panic("explicit panic") }
-        };
-    }
+        { ::std::rt::begin_panic("explicit panic") }
+    };
+}
 fn main() { }
diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs
index 3d052cc193c..dd6a7fa0e65 100644
--- a/tests/ui/wait-forked-but-failed-child.rs
+++ b/tests/ui/wait-forked-but-failed-child.rs
@@ -7,8 +7,6 @@
 
 #![feature(rustc_private)]
 
-extern crate libc;
-
 use std::process::Command;
 
 // The output from "ps -A -o pid,ppid,args" should look like this:
@@ -28,6 +26,7 @@ use std::process::Command;
 
 #[cfg(unix)]
 fn find_zombies() {
+    extern crate libc;
     let my_pid = unsafe { libc::getpid() };
 
     // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html