From 0a128da7588d4d235864e4c4903be89b5d851c2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Tue, 17 Aug 2021 00:00:00 +0000
Subject: [PATCH 1/6] Split critical edge targeting the start block

---
 .../src/transform/add_call_guards.rs          |  4 ++-
 ...issue-88043-bb-does-not-have-terminator.rs | 35 +++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs

diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir/src/transform/add_call_guards.rs
index 1dddaeb89e684..12ee6bb4c67fa 100644
--- a/compiler/rustc_mir/src/transform/add_call_guards.rs
+++ b/compiler/rustc_mir/src/transform/add_call_guards.rs
@@ -38,7 +38,9 @@ impl<'tcx> MirPass<'tcx> for AddCallGuards {
 
 impl AddCallGuards {
     pub fn add_call_guards(&self, body: &mut Body<'_>) {
-        let pred_count: IndexVec<_, _> = body.predecessors().iter().map(|ps| ps.len()).collect();
+        let mut pred_count: IndexVec<_, _> =
+            body.predecessors().iter().map(|ps| ps.len()).collect();
+        pred_count[START_BLOCK] += 1;
 
         // We need a place to store the new blocks generated
         let mut new_blocks = Vec::new();
diff --git a/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs b/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs
new file mode 100644
index 0000000000000..38dfca347c8cd
--- /dev/null
+++ b/src/test/ui/codegen/issue-88043-bb-does-not-have-terminator.rs
@@ -0,0 +1,35 @@
+// build-pass
+// compile-flags: -Copt-level=0
+
+// Regression test for #88043: LLVM crash when the RemoveZsts mir-opt pass is enabled.
+// We should not see the error:
+// `Basic Block in function '_ZN4main10take_until17h0067b8a660429bc9E' does not have terminator!`
+
+fn bump() -> Option<usize> {
+    unreachable!()
+}
+
+fn take_until(terminate: impl Fn() -> bool) {
+    loop {
+        if terminate() {
+            return;
+        } else {
+            bump();
+        }
+    }
+}
+
+// CHECK-LABEL: @main
+fn main() {
+    take_until(|| true);
+    f(None);
+}
+
+fn f(_a: Option<String>) -> Option<u32> {
+    loop {
+        g();
+        ()
+    }
+}
+
+fn g() -> Option<u32> { None }

From b842f8c7ff11dd4659def5a77de9f638ad7a4932 Mon Sep 17 00:00:00 2001
From: ibraheemdev <ibrah1440@gmail.com>
Date: Sat, 14 Aug 2021 00:02:02 -0400
Subject: [PATCH 2/6] make `BuildHasher` object safe

---
 library/core/src/hash/mod.rs            |  5 ++++-
 src/test/ui/build-hasher-object-safe.rs | 10 ++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/build-hasher-object-safe.rs

diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 9dbefe0822e36..8dec643255f64 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -520,7 +520,10 @@ pub trait BuildHasher {
     /// );
     /// ```
     #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")]
-    fn hash_one<T: Hash>(&self, x: T) -> u64 {
+    fn hash_one<T: Hash>(&self, x: T) -> u64
+    where
+        Self: Sized,
+    {
         let mut hasher = self.build_hasher();
         x.hash(&mut hasher);
         hasher.finish()
diff --git a/src/test/ui/build-hasher-object-safe.rs b/src/test/ui/build-hasher-object-safe.rs
new file mode 100644
index 0000000000000..50ec8e5e8d96e
--- /dev/null
+++ b/src/test/ui/build-hasher-object-safe.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+use std::hash::BuildHasher;
+use std::collections::hash_map::{DefaultHasher, RandomState};
+
+fn ensure_object_safe(_: &dyn BuildHasher<Hasher = DefaultHasher>) {}
+
+fn main() {
+    ensure_object_safe(&RandomState::new());
+}

From ca18f75c1b5373453d66f8ef0c33310abdaf89d3 Mon Sep 17 00:00:00 2001
From: ibraheemdev <ibrah1440@gmail.com>
Date: Sun, 15 Aug 2021 13:00:25 -0400
Subject: [PATCH 3/6] move object safety test to library/core

---
 library/core/tests/hash/mod.rs          |  9 ++++++++-
 src/test/ui/build-hasher-object-safe.rs | 10 ----------
 2 files changed, 8 insertions(+), 11 deletions(-)
 delete mode 100644 src/test/ui/build-hasher-object-safe.rs

diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index 1566d35749017..72ccdd4848a47 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -1,7 +1,7 @@
 mod sip;
 
 use std::default::Default;
-use std::hash::{Hash, Hasher};
+use std::hash::{BuildHasher, Hash, Hasher};
 use std::rc::Rc;
 
 struct MyHasher {
@@ -139,3 +139,10 @@ fn test_indirect_hasher() {
     }
     assert_eq!(hasher.hash, 5);
 }
+
+#[test]
+fn test_build_hasher_object_safe() {
+    use std::collections::hash_map::{DefaultHasher, RandomState};
+
+    let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
+}
diff --git a/src/test/ui/build-hasher-object-safe.rs b/src/test/ui/build-hasher-object-safe.rs
deleted file mode 100644
index 50ec8e5e8d96e..0000000000000
--- a/src/test/ui/build-hasher-object-safe.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-pass
-
-use std::hash::BuildHasher;
-use std::collections::hash_map::{DefaultHasher, RandomState};
-
-fn ensure_object_safe(_: &dyn BuildHasher<Hasher = DefaultHasher>) {}
-
-fn main() {
-    ensure_object_safe(&RandomState::new());
-}

From 3fd3b42e69fd3d5fd41e428c5a64850f32e366b4 Mon Sep 17 00:00:00 2001
From: Chris Denton <christophersdenton@gmail.com>
Date: Sun, 8 Aug 2021 14:23:08 +0100
Subject: [PATCH 4/6] Fix Windows Command::env("PATH")

---
 library/std/src/sys/windows/process.rs | 29 +++++++++++++++++++++-----
 library/std/src/sys_common/process.rs  | 10 +++++----
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 0fdf72c8067d2..ae193b82e91bb 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -3,7 +3,6 @@
 #[cfg(test)]
 mod tests;
 
-use crate::borrow::Borrow;
 use crate::cmp;
 use crate::collections::BTreeMap;
 use crate::convert::{TryFrom, TryInto};
@@ -46,6 +45,12 @@ pub struct EnvKey {
     utf16: Vec<u16>,
 }
 
+impl EnvKey {
+    fn new<T: Into<OsString>>(key: T) -> Self {
+        EnvKey::from(key.into())
+    }
+}
+
 // Comparing Windows environment variable keys[1] are behaviourally the
 // composition of two operations[2]:
 //
@@ -100,6 +105,20 @@ impl PartialEq for EnvKey {
         }
     }
 }
+impl PartialOrd<str> for EnvKey {
+    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+        Some(self.cmp(&EnvKey::new(other)))
+    }
+}
+impl PartialEq<str> for EnvKey {
+    fn eq(&self, other: &str) -> bool {
+        if self.os_string.len() != other.len() {
+            false
+        } else {
+            self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal
+        }
+    }
+}
 
 // Environment variable keys should preserve their original case even though
 // they are compared using a caseless string mapping.
@@ -115,9 +134,9 @@ impl From<EnvKey> for OsString {
     }
 }
 
-impl Borrow<OsStr> for EnvKey {
-    fn borrow(&self) -> &OsStr {
-        &self.os_string
+impl From<&OsStr> for EnvKey {
+    fn from(k: &OsStr) -> Self {
+        Self::from(k.to_os_string())
     }
 }
 
@@ -242,7 +261,7 @@ impl Command {
         // to read the *child's* PATH if one is provided. See #15149 for more
         // details.
         let program = maybe_env.as_ref().and_then(|env| {
-            if let Some(v) = env.get(OsStr::new("PATH")) {
+            if let Some(v) = env.get(&EnvKey::new("PATH")) {
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in split_paths(&v) {
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs
index fe89b11043c0f..38007d5c414ec 100644
--- a/library/std/src/sys_common/process.rs
+++ b/library/std/src/sys_common/process.rs
@@ -65,16 +65,18 @@ impl CommandEnv {
 
     // The following functions build up changes
     pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
-        self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
+        self.vars.insert(key, Some(value.to_owned()));
     }
 
     pub fn remove(&mut self, key: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
         if self.clear {
-            self.vars.remove(key);
+            self.vars.remove(&key);
         } else {
-            self.vars.insert(key.to_owned().into(), None);
+            self.vars.insert(key, None);
         }
     }
 
@@ -87,7 +89,7 @@ impl CommandEnv {
         self.saw_path || self.clear
     }
 
-    fn maybe_saw_path(&mut self, key: &OsStr) {
+    fn maybe_saw_path(&mut self, key: &EnvKey) {
         if !self.saw_path && key == "PATH" {
             self.saw_path = true;
         }

From 23c82af93718aaf872b81655fd903a7fbe2f5e5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Fri, 6 Aug 2021 02:36:54 -0700
Subject: [PATCH 5/6] Do not ICE on HIR based WF check when involving lifetimes

Fix #87549.
---
 .../src/traits/error_reporting/mod.rs         |  7 +++--
 src/test/ui/wf/hir-wf-check-erase-regions.rs  | 14 +++++++++
 .../ui/wf/hir-wf-check-erase-regions.stderr   | 31 +++++++++++++++++++
 3 files changed, 49 insertions(+), 3 deletions(-)
 create mode 100644 src/test/ui/wf/hir-wf-check-erase-regions.rs
 create mode 100644 src/test/ui/wf/hir-wf-check-erase-regions.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 13a6733fb478a..713e06f91d3f9 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -245,9 +245,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code.peel_derives()
                 {
-                    if let Some(cause) =
-                        self.tcx.diagnostic_hir_wf_check((obligation.predicate, wf_loc.clone()))
-                    {
+                    if let Some(cause) = self.tcx.diagnostic_hir_wf_check((
+                        tcx.erase_regions(obligation.predicate),
+                        wf_loc.clone(),
+                    )) {
                         obligation.cause = cause;
                         span = obligation.cause.span;
                     }
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.rs b/src/test/ui/wf/hir-wf-check-erase-regions.rs
new file mode 100644
index 0000000000000..bb398e5698a80
--- /dev/null
+++ b/src/test/ui/wf/hir-wf-check-erase-regions.rs
@@ -0,0 +1,14 @@
+// Regression test for #87549.
+// compile-flags: -C incremental=tmp/wf/hir-wf-check-erase-regions
+
+pub struct Table<T, const N: usize>([Option<T>; N]);
+
+impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
+    type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>; //~ ERROR `&T` is not an iterator
+    type Item = &'a T;
+
+    fn into_iter(self) -> Self::IntoIter { //~ ERROR `&T` is not an iterator
+        unimplemented!()
+    }
+}
+fn main() {}
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
new file mode 100644
index 0000000000000..203f09994e605
--- /dev/null
+++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
@@ -0,0 +1,31 @@
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:7:5
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
+   | 
+  ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+   |
+LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
+   |                                      ------------ required by this bound in `Flatten`
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+
+error[E0277]: `&T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:10:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
+   | 
+  ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+   |
+LL | pub struct Flatten<I: Iterator<Item: IntoIterator>> {
+   |                                      ------------ required by this bound in `Flatten`
+   |
+   = help: the trait `Iterator` is not implemented for `&T`
+   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.

From 88e4efd321c3c13b7b0d9ca13388f363a7b91363 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras <amanieu@gmail.com>
Date: Fri, 30 Jul 2021 18:56:48 +0200
Subject: [PATCH 6/6] Update compiler_builtins to fix i128 shift/mul on
 thumbv6m

Fixes #86063
---
 Cargo.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 30aa50982af61..60c1dea735325 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -646,9 +646,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.47"
+version = "0.1.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd4ed89e0a5c3e50b15c0045fbe1ff8567b703bc07544faf935ddff0aaa7b65f"
+checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",