From a809ec96f3cf5f5a73db24129392e64c8285bda8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <jieyouxu@outlook.com>
Date: Mon, 8 Apr 2024 21:18:51 +0000
Subject: [PATCH 1/9] test: check that `?` suggestion has local span

This can cause rustfix to crash because the `?` suggestion previously
could point into non-local spans, such as into the stdlib.
---
 .../question-mark-operator-suggestion-span.rs | 22 +++++++++++++
 ...stion-mark-operator-suggestion-span.stderr | 31 +++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 tests/ui/typeck/question-mark-operator-suggestion-span.rs
 create mode 100644 tests/ui/typeck/question-mark-operator-suggestion-span.stderr

diff --git a/tests/ui/typeck/question-mark-operator-suggestion-span.rs b/tests/ui/typeck/question-mark-operator-suggestion-span.rs
new file mode 100644
index 0000000000000..7aea6e63dd1f2
--- /dev/null
+++ b/tests/ui/typeck/question-mark-operator-suggestion-span.rs
@@ -0,0 +1,22 @@
+// Check that we don't construct a span for `?` suggestions that point into non-local macros
+// like into the stdlib where the user has no control over.
+//
+// FIXME(jieyouxu): this test is currently NOT run-rustfix because there are conflicting
+// MaybeIncorrect suggestions:
+//
+// 1. adding `return ... ;`, and
+// 2. adding `?`.
+//
+// When rustfix puts those together, the fixed file now contains uncompilable code.
+
+#![crate_type = "lib"]
+
+pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
+    if true {
+        writeln!(w, "`;?` here ->")?;
+    } else {
+        writeln!(w, "but not here")
+        //~^ ERROR mismatched types
+    }
+    Ok(())
+}
diff --git a/tests/ui/typeck/question-mark-operator-suggestion-span.stderr b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
new file mode 100644
index 0000000000000..089b3bcd1988a
--- /dev/null
+++ b/tests/ui/typeck/question-mark-operator-suggestion-span.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/question-mark-operator-suggestion-span.rs:18:9
+   |
+LL | /     if true {
+LL | |         writeln!(w, "`;?` here ->")?;
+LL | |     } else {
+LL | |         writeln!(w, "but not here")
+   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
+LL | |
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<(), std::fmt::Error>`
+   = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using a semicolon here
+   |
+LL |     };
+   |      +
+help: you might have meant to return this value
+   |
+LL |         return writeln!(w, "but not here");
+   |         ++++++                            +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!(w, "but not here")?
+   |                                    +
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.

From 4606485d0c36676f08a61c524dbc2ee05bbfb049 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <jieyouxu@outlook.com>
Date: Mon, 8 Apr 2024 21:42:06 +0000
Subject: [PATCH 2/9] typeck: fix `?` operator suggestion span

---
 .../src/fn_ctxt/suggestions.rs                | 15 ++-----
 compiler/rustc_span/src/lib.rs                | 39 +++++++++++++++++++
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 442bfd75746ee..4a956595f1521 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1291,12 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
             ))
         {
-            let mut span = expr.span;
-            while expr.span.eq_ctxt(span)
-                && let Some(parent_callsite) = span.parent_callsite()
-            {
-                span = parent_callsite;
-            }
+            let span = expr.span.find_oldest_ancestor_in_same_ctxt();
 
             let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
                 vec![(span.shrink_to_hi(), ".into()".to_owned())]
@@ -1901,12 +1896,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             None => sugg.to_string(),
         };
 
-        err.span_suggestion_verbose(
-            expr.span.shrink_to_hi(),
-            msg,
-            sugg,
-            Applicability::HasPlaceholders,
-        );
+        let span = expr.span.find_oldest_ancestor_in_same_ctxt();
+        err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders);
         return true;
     }
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 7ce879807cae1..c1e1175b4bd6b 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -743,6 +743,45 @@ impl Span {
         Some(self)
     }
 
+    /// Recursively walk down the expansion ancestors to find the oldest ancestor span with the same
+    /// [`SyntaxContext`] the initial span.
+    ///
+    /// This method is suitable for peeling through *local* macro expansions to find the "innermost"
+    /// span that is still local and shares the same [`SyntaxContext`]. For example, given
+    ///
+    /// ```ignore (illustrative example, contains type error)
+    ///  macro_rules! outer {
+    ///      ($x: expr) => {
+    ///          inner!($x)
+    ///      }
+    ///  }
+    ///
+    ///  macro_rules! inner {
+    ///      ($x: expr) => {
+    ///          format!("error: {}", $x)
+    ///          //~^ ERROR mismatched types
+    ///      }
+    ///  }
+    ///
+    ///  fn bar(x: &str) -> Result<(), Box<dyn std::error::Error>> {
+    ///      Err(outer!(x))
+    ///  }
+    /// ```
+    ///
+    /// if provided the initial span of `outer!(x)` inside `bar`, this method will recurse
+    /// the parent callsites until we reach `format!("error: {}", $x)`, at which point it is the
+    /// oldest ancestor span that is both still local and shares the same [`SyntaxContext`] as the
+    /// initial span.
+    pub fn find_oldest_ancestor_in_same_ctxt(self) -> Span {
+        let mut cur = self;
+        while cur.eq_ctxt(self)
+            && let Some(parent_callsite) = cur.parent_callsite()
+        {
+            cur = parent_callsite;
+        }
+        cur
+    }
+
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
         self.ctxt().edition()

From 420e3f1d5cf8e156d6f4ae636ce5bbaa6b7c9c70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <jieyouxu@outlook.com>
Date: Mon, 8 Apr 2024 23:17:18 +0000
Subject: [PATCH 3/9] test: avoid running rustfix on leaked writeln macro
 internals test

This test contains conflicting MaybeIncorrect suggestions which will
cause the fixed file to not compile.
---
 ...12007-leaked-writeln-macro-internals.fixed | 37 -------------------
 ...e-112007-leaked-writeln-macro-internals.rs | 18 ++++++---
 ...2007-leaked-writeln-macro-internals.stderr | 12 +++++-
 3 files changed, 23 insertions(+), 44 deletions(-)
 delete mode 100644 tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed

diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed
deleted file mode 100644
index dcb256de18f17..0000000000000
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.fixed
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ run-rustfix
-#![allow(dead_code)]
-
-// https://github.com/rust-lang/rust/issues/112007
-fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
-    if true {
-        writeln!(w, "`;?` here ->")?;
-    } else {
-        return writeln!(w, "but not here");
-        //~^ ERROR mismatched types
-    };
-    Ok(())
-}
-
-macro_rules! baz {
-    ($w: expr) => {
-        bar!($w)
-    }
-}
-
-macro_rules! bar {
-    ($w: expr) => {
-        writeln!($w, "but not here")
-        //~^ ERROR mismatched types
-    }
-}
-
-fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
-    if true {
-        writeln!(w, "`;?` here ->")?;
-    } else {
-        return baz!(w);
-    };
-    Ok(())
-}
-
-fn main() {}
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
index 58cd6cbf20c57..7ec9f0d4cdb9c 100644
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
+++ b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.rs
@@ -1,8 +1,16 @@
-//@ run-rustfix
-#![allow(dead_code)]
+// Check that we don't leak stdlib implementation details through suggestions.
+// Also check that the suggestion provided tries as hard as it can to see through local macros.
+//
+// FIXME(jieyouxu): this test is NOT run-rustfix because this test contains conflicting
+// MaybeIncorrect suggestions:
+//
+// 1. `return ... ;`
+// 2. `?`
+//
+// when the suggestions are applied to the same file, it becomes uncompilable.
 
 // https://github.com/rust-lang/rust/issues/112007
-fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
+pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     if true {
         writeln!(w, "`;?` here ->")?;
     } else {
@@ -25,7 +33,7 @@ macro_rules! bar {
     }
 }
 
-fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
+pub fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     if true {
         writeln!(w, "`;?` here ->")?;
     } else {
@@ -34,4 +42,4 @@ fn foo<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
     Ok(())
 }
 
-fn main() {}
+pub fn main() {}
diff --git a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
index df2e06e8f3b76..889d2c94d0cfb 100644
--- a/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
+++ b/tests/ui/typeck/issue-112007-leaked-writeln-macro-internals.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:9:9
+  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:17:9
    |
 LL | /     if true {
 LL | |         writeln!(w, "`;?` here ->")?;
@@ -21,9 +21,13 @@ help: you might have meant to return this value
    |
 LL |         return writeln!(w, "but not here");
    |         ++++++                            +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!(w, "but not here")?
+   |                                    +
 
 error[E0308]: mismatched types
-  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:32:9
+  --> $DIR/issue-112007-leaked-writeln-macro-internals.rs:40:9
    |
 LL | /     if true {
 LL | |         writeln!(w, "`;?` here ->")?;
@@ -44,6 +48,10 @@ help: you might have meant to return this value
    |
 LL |         return baz!(w);
    |         ++++++        +
+help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
+   |
+LL |         writeln!($w, "but not here")?
+   |                                     +
 
 error: aborting due to 2 previous errors
 

From 843cef303538f4aeaaf899c6f0529008dcc1369c Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Thu, 11 Apr 2024 18:49:45 +0200
Subject: [PATCH 4/9] std: remove `sys_common::thread`

---
 library/std/src/sys_common/mod.rs    |  1 -
 library/std/src/sys_common/thread.rs | 18 ------------------
 library/std/src/thread/mod.rs        | 27 ++++++++++++++++++++++-----
 3 files changed, 22 insertions(+), 24 deletions(-)
 delete mode 100644 library/std/src/sys_common/thread.rs

diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 5abf201aa201b..cc21560fff505 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -25,7 +25,6 @@ pub mod fs;
 pub mod io;
 pub mod lazy_box;
 pub mod process;
-pub mod thread;
 pub mod thread_local_dtor;
 pub mod thread_parking;
 pub mod wstr;
diff --git a/library/std/src/sys_common/thread.rs b/library/std/src/sys_common/thread.rs
deleted file mode 100644
index 8f5624bbce9da..0000000000000
--- a/library/std/src/sys_common/thread.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use crate::env;
-use crate::sync::atomic::{self, Ordering};
-use crate::sys::thread as imp;
-
-pub fn min_stack() -> usize {
-    static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
-    match MIN.load(Ordering::Relaxed) {
-        0 => {}
-        n => return n - 1,
-    }
-    let amt = env::var_os("RUST_MIN_STACK").and_then(|s| s.to_str().and_then(|s| s.parse().ok()));
-    let amt = amt.unwrap_or(imp::DEFAULT_MIN_STACK_SIZE);
-
-    // 0 is our sentinel value, so ensure that we'll never see 0 after
-    // initialization has run
-    MIN.store(amt + 1, Ordering::Relaxed);
-    amt
-}
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index f792a27dd694d..fd89edd4acebe 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -160,6 +160,7 @@ mod tests;
 
 use crate::any::Any;
 use crate::cell::{OnceCell, UnsafeCell};
+use crate::env;
 use crate::ffi::{CStr, CString};
 use crate::fmt;
 use crate::io;
@@ -171,9 +172,9 @@ use crate::panicking;
 use crate::pin::Pin;
 use crate::ptr::addr_of_mut;
 use crate::str;
+use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sync::Arc;
 use crate::sys::thread as imp;
-use crate::sys_common::thread;
 use crate::sys_common::thread_parking::Parker;
 use crate::sys_common::{AsInner, IntoInner};
 use crate::time::{Duration, Instant};
@@ -468,7 +469,23 @@ impl Builder {
     {
         let Builder { name, stack_size } = self;
 
-        let stack_size = stack_size.unwrap_or_else(thread::min_stack);
+        let stack_size = stack_size.unwrap_or_else(|| {
+            static MIN: AtomicUsize = AtomicUsize::new(0);
+
+            match MIN.load(Ordering::Relaxed) {
+                0 => {}
+                n => return n - 1,
+            }
+
+            let amt = env::var_os("RUST_MIN_STACK")
+                .and_then(|s| s.to_str().and_then(|s| s.parse().ok()))
+                .unwrap_or(imp::DEFAULT_MIN_STACK_SIZE);
+
+            // 0 is our sentinel value, so ensure that we'll never see 0 after
+            // initialization has run
+            MIN.store(amt + 1, Ordering::Relaxed);
+            amt
+        });
 
         let my_thread = Thread::new(name.map(|name| {
             CString::new(name).expect("thread name may not contain interior null bytes")
@@ -1191,17 +1208,17 @@ impl ThreadId {
 
         cfg_if::cfg_if! {
             if #[cfg(target_has_atomic = "64")] {
-                use crate::sync::atomic::{AtomicU64, Ordering::Relaxed};
+                use crate::sync::atomic::AtomicU64;
 
                 static COUNTER: AtomicU64 = AtomicU64::new(0);
 
-                let mut last = COUNTER.load(Relaxed);
+                let mut last = COUNTER.load(Ordering::Relaxed);
                 loop {
                     let Some(id) = last.checked_add(1) else {
                         exhausted();
                     };
 
-                    match COUNTER.compare_exchange_weak(last, id, Relaxed, Relaxed) {
+                    match COUNTER.compare_exchange_weak(last, id, Ordering::Relaxed, Ordering::Relaxed) {
                         Ok(_) => return ThreadId(NonZero::new(id).unwrap()),
                         Err(id) => last = id,
                     }

From 1ce559b69096fc1cfd306a80250fddb52168d7f4 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen@gmail.com>
Date: Fri, 12 Apr 2024 16:41:29 +0100
Subject: [PATCH 5/9] std::net: TcpListener shrinks the backlog argument to 32
 for Haiku.

---
 library/std/src/sys_common/net.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 8c9885974b481..6a268633f72c1 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -417,6 +417,10 @@ impl TcpListener {
                 // it allows up to about 37, but other times it doesn't even
                 // accept 32. There may be a global limitation causing this.
                 let backlog = 20;
+            } else if #[cfg(target_os = "haiku")] {
+                // Haiku does not support a queue length > 32
+                // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
+                let backlog = 32;
             } else {
                 // The default for all other platforms
                 let backlog = 128;

From 49e73c3e0194336c5eee8229afe9ffa79daa2c4f Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 11 Apr 2024 20:23:35 -0400
Subject: [PATCH 6/9] Don't do coroutine-closure-specific upvar analysis if
 tainted by errors

---
 compiler/rustc_hir_typeck/src/upvar.rs        |  8 +++++--
 compiler/rustc_middle/src/ty/sty.rs           |  2 +-
 .../dont-ice-when-body-tainted-by-errors.rs   | 23 +++++++++++++++++++
 ...ont-ice-when-body-tainted-by-errors.stderr | 20 ++++++++++++++++
 4 files changed, 50 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
 create mode 100644 tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr

diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index ef569b4bef3b3..86f36eedd9007 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -43,7 +43,8 @@ use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, Pro
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::{
-    self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
+    self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs,
+    UpvarCapture,
 };
 use rustc_session::lint;
 use rustc_span::sym;
@@ -191,6 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             }
         };
+        let args = self.resolve_vars_if_possible(args);
         let closure_def_id = closure_def_id.expect_local();
 
         assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
@@ -361,7 +363,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // For coroutine-closures, we additionally must compute the
         // `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref
         // version of the coroutine-closure's output coroutine.
-        if let UpvarArgs::CoroutineClosure(args) = args {
+        if let UpvarArgs::CoroutineClosure(args) = args
+            && !args.references_error()
+        {
             let closure_env_region: ty::Region<'_> = ty::Region::new_bound(
                 self.tcx,
                 ty::INNERMOST,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index dd73f0f4a350d..ad64745d579a0 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -771,7 +771,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
     }
 }
 
-#[derive(Debug, Copy, Clone, HashStable)]
+#[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]
 pub enum UpvarArgs<'tcx> {
     Closure(GenericArgsRef<'tcx>),
     Coroutine(GenericArgsRef<'tcx>),
diff --git a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
new file mode 100644
index 0000000000000..8fc9924a12fb0
--- /dev/null
+++ b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.rs
@@ -0,0 +1,23 @@
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+struct DropMe;
+
+trait Impossible {}
+fn trait_error<T: Impossible>() {}
+
+pub fn main() {
+    let b = DropMe;
+    let async_closure = async move || {
+        // Type error here taints the environment. This causes us to fallback all
+        // variables to `Error`. This means that when we compute the upvars for the
+        // *outer* coroutine-closure, we don't actually see any upvars since `MemCategorization`
+        // and `ExprUseVisitor`` will bail early when it sees error. This means
+        // that our underlying assumption that the parent and child captures are
+        // compatible ends up being broken, previously leading to an ICE.
+        trait_error::<()>();
+        //~^ ERROR the trait bound `(): Impossible` is not satisfied
+        let _b = b;
+    };
+}
diff --git a/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr
new file mode 100644
index 0000000000000..b4dc3e268bdaf
--- /dev/null
+++ b/tests/ui/async-await/async-closures/dont-ice-when-body-tainted-by-errors.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the trait bound `(): Impossible` is not satisfied
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:19:23
+   |
+LL |         trait_error::<()>();
+   |                       ^^ the trait `Impossible` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:7:1
+   |
+LL | trait Impossible {}
+   | ^^^^^^^^^^^^^^^^
+note: required by a bound in `trait_error`
+  --> $DIR/dont-ice-when-body-tainted-by-errors.rs:8:19
+   |
+LL | fn trait_error<T: Impossible>() {}
+   |                   ^^^^^^^^^^ required by this bound in `trait_error`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.

From 861e213f878d1e0412a6eb57ba33025adf047bee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marijan=20Petri=C4=8Devi=C4=87?=
 <marijan.petricevic94@gmail.com>
Date: Fri, 12 Apr 2024 11:28:35 -0500
Subject: [PATCH 7/9] zkvm: remove cmath

- Remove cmath from zkvm module since cmath was moved to sys and is
shared by all platforms (see #120109)
---
 library/std/src/sys/pal/zkvm/mod.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index 62f0a2c7b1c18..4f79f8c496169 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -12,8 +12,6 @@ const WORD_SIZE: usize = core::mem::size_of::<u32>();
 pub mod alloc;
 #[path = "../zkvm/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 #[path = "../unsupported/fs.rs"]
 pub mod fs;

From ddcfb94b84835edad5a223db3f226c7b302d264c Mon Sep 17 00:00:00 2001
From: Alan Egerton <eggyal@gmail.com>
Date: Fri, 12 Apr 2024 12:33:03 +0100
Subject: [PATCH 8/9] Suppress erroneous suggestion

The suggestion to use `let else` with an uninitialized refutable `let`
statement was erroneous: `let else` cannot be used with deferred
initialization.
---
 .../src/thir/pattern/check_match.rs           |  1 +
 ...pats-inclusive-dotdotdot-bad-syntax.stderr |  4 ---
 ...lf-open-range-pats-inclusive-no-end.stderr |  8 -----
 ...ninitialized-refutable-let-issue-123844.rs |  8 +++++
 ...tialized-refutable-let-issue-123844.stderr | 13 +++++++
 .../parser/recover/recover-range-pats.stderr  | 36 -------------------
 6 files changed, 22 insertions(+), 48 deletions(-)
 create mode 100644 tests/ui/let-else/uninitialized-refutable-let-issue-123844.rs
 create mode 100644 tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr

diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index a3e6c2abc51fa..03195a122b485 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -674,6 +674,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
         if let Some(span) = sp
             && self.tcx.sess.source_map().is_span_accessible(span)
             && interpreted_as_const.is_none()
+            && scrut.is_some()
         {
             let mut bindings = vec![];
             pat.each_binding(|name, _, _, _| bindings.push(name));
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
index 6832f21f25e99..0d2aae689f037 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
@@ -46,10 +46,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let ...$e; { todo!() }
-   |             ++            +++++++++++
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
index cb9e48e70e391..9ba0e09e1540c 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
@@ -67,10 +67,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let $e...; { todo!() }
-   |             ++            +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17
@@ -85,10 +81,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let $e..=; { todo!() }
-   |             ++            +++++++++++
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/let-else/uninitialized-refutable-let-issue-123844.rs b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.rs
new file mode 100644
index 0000000000000..8426b0021f497
--- /dev/null
+++ b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-lang/rust/issues/123844
+// An uninitialized refutable let should not suggest `let else`, as it can't be used with deferred
+// initialization.
+
+fn main() {
+    let Some(x); //~ ERROR refutable pattern in local binding
+    x = 1;
+}
diff --git a/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr
new file mode 100644
index 0000000000000..13312306c07b7
--- /dev/null
+++ b/tests/ui/let-else/uninitialized-refutable-let-issue-123844.stderr
@@ -0,0 +1,13 @@
+error[E0005]: refutable pattern in local binding
+  --> $DIR/uninitialized-refutable-let-issue-123844.rs:6:9
+   |
+LL |     let Some(x);
+   |         ^^^^^^^ pattern `None` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Option<i32>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr
index 7c5cc4777b6b4..2c0baf7e5f80b 100644
--- a/tests/ui/parser/recover/recover-range-pats.stderr
+++ b/tests/ui/parser/recover/recover-range-pats.stderr
@@ -491,10 +491,6 @@ LL |     mac2!(0, 1);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variants that aren't matched
-   |
-LL |             if let $e1..$e2; { todo!() }
-   |             ++               +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:138:17
@@ -509,10 +505,6 @@ LL |     mac2!(0, 1);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variants that aren't matched
-   |
-LL |             if let $e1...$e2; { todo!() }
-   |             ++                +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:142:17
@@ -527,10 +519,6 @@ LL |     mac2!(0, 1);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variants that aren't matched
-   |
-LL |             if let $e1..=$e2; { todo!() }
-   |             ++                +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:151:17
@@ -545,10 +533,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let ..$e; { todo!() }
-   |             ++           +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:153:17
@@ -563,10 +547,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let ...$e; { todo!() }
-   |             ++            +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:156:17
@@ -581,10 +561,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let ..=$e; { todo!() }
-   |             ++            +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:158:17
@@ -599,10 +575,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let $e..; { todo!() }
-   |             ++           +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:160:17
@@ -617,10 +589,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let $e...; { todo!() }
-   |             ++            +++++++++++
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/recover-range-pats.rs:162:17
@@ -635,10 +603,6 @@ LL |     mac!(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |             if let $e..=; { todo!() }
-   |             ++            +++++++++++
 
 error: aborting due to 69 previous errors
 

From a6ed319e1b1391181d08a40e3fb8f8a1412d2222 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io>
Date: Fri, 12 Apr 2024 20:47:59 +0200
Subject: [PATCH 9/9] Add `unsafe` to two functions with safety invariants

---
 library/std/src/sys/pal/windows/thread.rs | 26 ++++++++++++-----------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index 34d90a3b4a0dc..70099e0a3b560 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -45,13 +45,11 @@ impl Thread {
             Err(io::Error::last_os_error())
         };
 
-        extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
-            unsafe {
-                // Next, reserve some stack space for if we otherwise run out of stack.
-                stack_overflow::reserve_stack();
-                // Finally, let's run some code.
-                Box::from_raw(main as *mut Box<dyn FnOnce()>)();
-            }
+        unsafe extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
+            // Next, reserve some stack space for if we otherwise run out of stack.
+            stack_overflow::reserve_stack();
+            // Finally, let's run some code.
+            Box::from_raw(main as *mut Box<dyn FnOnce()>)();
             0
         }
     }
@@ -59,15 +57,19 @@ impl Thread {
     pub fn set_name(name: &CStr) {
         if let Ok(utf8) = name.to_str() {
             if let Ok(utf16) = to_u16s(utf8) {
-                Self::set_name_wide(&utf16)
+                unsafe {
+                    // SAFETY: the vec returned by `to_u16s` ends with a zero value
+                    Self::set_name_wide(&utf16)
+                }
             };
         };
     }
 
-    pub fn set_name_wide(name: &[u16]) {
-        unsafe {
-            c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
-        };
+    /// # Safety
+    ///
+    /// `name` must end with a zero value
+    pub unsafe fn set_name_wide(name: &[u16]) {
+        c::SetThreadDescription(c::GetCurrentThread(), name.as_ptr());
     }
 
     pub fn join(self) {