From 09a3dfc351955999953195aad0706304acf1ef1a Mon Sep 17 00:00:00 2001
From: Michael Howell <michael@notriddle.com>
Date: Tue, 2 Aug 2022 13:24:34 -0700
Subject: [PATCH 01/10] rustdoc: use a more compact encoding for
 source-files.js

This reduces the compiler-doc file from 40K to 36K, a 10% reduction in size.
---
 src/librustdoc/html/render/write_shared.rs    | 33 +++++++++++--------
 .../html/static/js/source-script.js           | 18 ++++++----
 2 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 27ad91d09e064..6fb41ff327916 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -366,13 +366,15 @@ pub(super) fn write_shared(
                 .collect::<Vec<_>>();
             files.sort_unstable();
             let subs = subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(",");
-            let dirs =
-                if subs.is_empty() { String::new() } else { format!(",\"dirs\":[{}]", subs) };
+            let dirs = if subs.is_empty() && files.is_empty() {
+                String::new()
+            } else {
+                format!(",[{}]", subs)
+            };
             let files = files.join(",");
-            let files =
-                if files.is_empty() { String::new() } else { format!(",\"files\":[{}]", files) };
+            let files = if files.is_empty() { String::new() } else { format!(",[{}]", files) };
             format!(
-                "{{\"name\":\"{name}\"{dirs}{files}}}",
+                "[\"{name}\"{dirs}{files}]",
                 name = self.elem.to_str().expect("invalid osstring conversion"),
                 dirs = dirs,
                 files = files
@@ -411,18 +413,23 @@ pub(super) fn write_shared(
         let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
         let make_sources = || {
             let (mut all_sources, _krates) =
-                try_err!(collect(&dst, krate.name(cx.tcx()).as_str(), "sourcesIndex"), &dst);
+                try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst);
             all_sources.push(format!(
-                "sourcesIndex[\"{}\"] = {};",
+                r#""{}":{}"#,
                 &krate.name(cx.tcx()),
-                hierarchy.to_json_string()
+                hierarchy
+                    .to_json_string()
+                    // All these `replace` calls are because we have to go through JS string for JSON content.
+                    .replace('\\', r"\\")
+                    .replace('\'', r"\'")
+                    // We need to escape double quotes for the JSON.
+                    .replace("\\\"", "\\\\\"")
             ));
             all_sources.sort();
-            Ok(format!(
-                "var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n",
-                all_sources.join("\n")
-            )
-            .into_bytes())
+            let mut v = String::from("var sourcesIndex = JSON.parse('{\\\n");
+            v.push_str(&all_sources.join(",\\\n"));
+            v.push_str("\\\n}');\ncreateSourceSidebar();\n");
+            Ok(v.into_bytes())
         };
         write_crate("source-files.js", &make_sources)?;
     }
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index a6a0b09ef31fe..c45d614293a85 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -12,6 +12,10 @@
 const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
 let oldScrollPosition = 0;
 
+const NAME_OFFSET = 0;
+const DIRS_OFFSET = 1;
+const FILES_OFFSET = 2;
+
 function closeSidebarIfMobile() {
     if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
         updateLocalStorage("source-sidebar-show", "false");
@@ -24,15 +28,15 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
 
     dirEntry.className = "dir-entry";
 
-    fullPath += elem["name"] + "/";
+    fullPath += elem[NAME_OFFSET] + "/";
 
-    summary.innerText = elem["name"];
+    summary.innerText = elem[NAME_OFFSET];
     dirEntry.appendChild(summary);
 
     const folders = document.createElement("div");
     folders.className = "folders";
-    if (elem.dirs) {
-        for (const dir of elem.dirs) {
+    if (elem[DIRS_OFFSET]) {
+        for (const dir of elem[DIRS_OFFSET]) {
             if (createDirEntry(dir, folders, fullPath, false)) {
                 dirEntry.open = true;
                 hasFoundFile = true;
@@ -43,8 +47,8 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
 
     const files = document.createElement("div");
     files.className = "files";
-    if (elem.files) {
-        for (const file_text of elem.files) {
+    if (elem[FILES_OFFSET]) {
+        for (const file_text of elem[FILES_OFFSET]) {
             const file = document.createElement("a");
             file.innerText = file_text;
             file.href = rootPath + "src/" + fullPath + file_text + ".html";
@@ -125,7 +129,7 @@ function createSourceSidebar() {
     title.innerText = "Files";
     sidebar.appendChild(title);
     Object.keys(sourcesIndex).forEach(key => {
-        sourcesIndex[key].name = key;
+        sourcesIndex[key][NAME_OFFSET] = key;
         hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
             hasFoundFile);
     });

From 9cf556dca9e4fb731035a51e75974c78d52295ce Mon Sep 17 00:00:00 2001
From: Daniel Sommermann <dcsommer@gmail.com>
Date: Mon, 1 Aug 2022 11:47:32 -0700
Subject: [PATCH 02/10] Fix backwards-compatibility check for tests with
 `+whole-archive`

Fixes #100066
---
 compiler/rustc_codegen_ssa/src/back/link.rs   |  2 +-
 .../Makefile                                  | 19 ++++++++++++++++---
 ...irectly_linked_test_minus_whole_archive.rs |  7 +++++++
 ...directly_linked_test_plus_whole_archive.rs |  7 +++++++
 4 files changed, 31 insertions(+), 4 deletions(-)
 create mode 100644 src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
 create mode 100644 src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs

diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 13a7b6be947ec..326dce8011eae 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -2267,7 +2267,7 @@ fn add_local_native_libraries(
                     // be added explicitly if necessary, see the error in `fn link_rlib`) compiled
                     // as an executable due to `--test`. Use whole-archive implicitly, like before
                     // the introduction of native lib modifiers.
-                    || (bundle != Some(false) && sess.opts.test)
+                    || (whole_archive == None && bundle != Some(false) && sess.opts.test)
                 {
                     cmd.link_whole_staticlib(
                         name,
diff --git a/src/test/run-make/native-link-modifier-whole-archive/Makefile b/src/test/run-make/native-link-modifier-whole-archive/Makefile
index 3b49d1188ae6b..967cb065cad1a 100644
--- a/src/test/run-make/native-link-modifier-whole-archive/Makefile
+++ b/src/test/run-make/native-link-modifier-whole-archive/Makefile
@@ -1,7 +1,7 @@
 # ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
 
-# This test case makes sure that native libraries are linked with --whole-archive semantics
-# when the `-bundle,+whole-archive` modifiers are applied to them.
+# This test case makes sure that native libraries are linked with appropriate semantics
+# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
 #
 # The test works by checking that the resulting executables produce the expected output,
 # part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
@@ -10,8 +10,14 @@
 
 -include ../../run-make-fulldeps/tools.mk
 
-all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linked) $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
+all: $(TMPDIR)/$(call BIN,directly_linked) \
+     $(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
+     $(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
+     $(TMPDIR)/$(call BIN,indirectly_linked) \
+     $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
 	$(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
+	$(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
+	$(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
 	$(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
 	$(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
 
@@ -19,6 +25,13 @@ all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linke
 $(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
 	$(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
 
+# Native lib linked into test executable, +whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
+# Native lib linked into test executable, -whole-archive
+$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+	$(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
+
 # Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
 $(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
 	$(RUSTC) indirectly_linked.rs
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
new file mode 100644
index 0000000000000..20ed8d9d4cd10
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_minus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+    print!("ran the test");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
new file mode 100644
index 0000000000000..20ed8d9d4cd10
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked_test_plus_whole_archive.rs
@@ -0,0 +1,7 @@
+use std::io::Write;
+
+#[test]
+fn test_thing() {
+    print!("ran the test");
+    std::io::stdout().flush().unwrap();
+}

From 6f87b7500a3450f41c82dd5eca58460b4ef7a30c Mon Sep 17 00:00:00 2001
From: topjohnwu <topjohnwu@google.com>
Date: Wed, 3 Aug 2022 01:54:24 -0700
Subject: [PATCH 03/10] Set llvm configs when building lld

---
 src/bootstrap/native.rs | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 3347246ea8f6f..4d548dbb63875 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -345,13 +345,6 @@ impl Step for Llvm {
             cfg.define("LLVM_ENABLE_ZLIB", "OFF");
         }
 
-        if builder.config.llvm_thin_lto {
-            cfg.define("LLVM_ENABLE_LTO", "Thin");
-            if !target.contains("apple") {
-                cfg.define("LLVM_ENABLE_LLD", "ON");
-            }
-        }
-
         // This setting makes the LLVM tools link to the dynamic LLVM library,
         // which saves both memory during parallel links and overall disk space
         // for the tools. We don't do this on every platform as it doesn't work
@@ -463,15 +456,8 @@ impl Step for Llvm {
             cfg.define("LLVM_VERSION_SUFFIX", suffix);
         }
 
-        if let Some(ref linker) = builder.config.llvm_use_linker {
-            cfg.define("LLVM_USE_LINKER", linker);
-        }
-
-        if builder.config.llvm_allow_old_toolchain {
-            cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
-        }
-
         configure_cmake(builder, target, &mut cfg, true, ldflags);
+        configure_llvm(builder, target, &mut cfg);
 
         for (key, val) in &builder.config.llvm_build_config {
             cfg.define(key, val);
@@ -731,6 +717,25 @@ fn configure_cmake(
     }
 }
 
+fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmake::Config) {
+    // ThinLTO is only available when building with LLVM, enabling LLD is required.
+    // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin.
+    if builder.config.llvm_thin_lto {
+        cfg.define("LLVM_ENABLE_LTO", "Thin");
+        if !target.contains("apple") {
+            cfg.define("LLVM_ENABLE_LLD", "ON");
+        }
+    }
+
+    if let Some(ref linker) = builder.config.llvm_use_linker {
+        cfg.define("LLVM_USE_LINKER", linker);
+    }
+
+    if builder.config.llvm_allow_old_toolchain {
+        cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
+    }
+}
+
 // Adapted from https://github.com/alexcrichton/cc-rs/blob/fba7feded71ee4f63cfe885673ead6d7b4f2f454/src/lib.rs#L2347-L2365
 fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
     let kind = if host == target { "HOST" } else { "TARGET" };
@@ -794,6 +799,7 @@ impl Step for Lld {
         }
 
         configure_cmake(builder, target, &mut cfg, true, ldflags);
+        configure_llvm(builder, target, &mut cfg);
 
         // This is an awful, awful hack. Discovered when we migrated to using
         // clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
@@ -825,10 +831,6 @@ impl Step for Lld {
             .define("LLVM_CONFIG_PATH", llvm_config_shim)
             .define("LLVM_INCLUDE_TESTS", "OFF");
 
-        if builder.config.llvm_allow_old_toolchain {
-            cfg.define("LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN", "YES");
-        }
-
         // While we're using this horrible workaround to shim the execution of
         // llvm-config, let's just pile on more. I can't seem to figure out how
         // to build LLD as a standalone project and also cross-compile it at the

From 1405ce35acbcd61b9da8ab7ded6201639cb83d52 Mon Sep 17 00:00:00 2001
From: b-naber <bn263@gmx.de>
Date: Wed, 3 Aug 2022 11:04:10 +0200
Subject: [PATCH 04/10] fix typo

---
 compiler/rustc_infer/src/infer/higher_ranked/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index e543ae1fcdab1..4608d3984ac1d 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -16,7 +16,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
     ///
     /// This is implemented by first entering a new universe.
     /// We then replace all bound variables in `sup` with placeholders,
-    /// and all bound variables in `sup` with inference vars.
+    /// and all bound variables in `sub` with inference vars.
     /// We can then just relate the two resulting types as normal.
     ///
     /// Note: this is a subtle algorithm. For a full explanation, please see

From a72e96c4277d820f294a6bfb3ced7ffbd3db1b6e Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Wed, 3 Aug 2022 11:35:32 +0200
Subject: [PATCH 05/10] remove Clean trait implementation for ty::Region

---
 src/librustdoc/clean/mod.rs   | 59 ++++++++++++++++++-----------------
 src/librustdoc/clean/utils.rs |  8 ++---
 2 files changed, 34 insertions(+), 33 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 4777f9c96e6ee..9e83021a5fbe4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -242,30 +242,28 @@ pub(crate) fn clean_middle_const<'tcx>(
     }
 }
 
-impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::Region<'tcx> {
-    fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
-        match **self {
-            ty::ReStatic => Some(Lifetime::statik()),
-            ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
-                if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
-            }
-            ty::ReEarlyBound(ref data) => {
-                if data.name != kw::UnderscoreLifetime {
-                    Some(Lifetime(data.name))
-                } else {
-                    None
-                }
-            }
-            ty::ReLateBound(..)
-            | ty::ReFree(..)
-            | ty::ReVar(..)
-            | ty::RePlaceholder(..)
-            | ty::ReEmpty(_)
-            | ty::ReErased => {
-                debug!("cannot clean region {:?}", self);
+pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
+    match *region {
+        ty::ReStatic => Some(Lifetime::statik()),
+        ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
+            if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
+        }
+        ty::ReEarlyBound(ref data) => {
+            if data.name != kw::UnderscoreLifetime {
+                Some(Lifetime(data.name))
+            } else {
                 None
             }
         }
+        ty::ReLateBound(..)
+        | ty::ReFree(..)
+        | ty::ReVar(..)
+        | ty::RePlaceholder(..)
+        | ty::ReEmpty(_)
+        | ty::ReErased => {
+            debug!("cannot clean region {:?}", region);
+            None
+        }
     }
 }
 
@@ -316,7 +314,7 @@ impl<'tcx> Clean<'tcx, Option<WherePredicate>> for ty::Predicate<'tcx> {
             ty::PredicateKind::Trait(pred) => {
                 clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
             }
-            ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred, cx),
+            ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
             ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
             ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
             ty::PredicateKind::ConstEvaluatable(..) => None,
@@ -353,7 +351,6 @@ fn clean_poly_trait_predicate<'tcx>(
 
 fn clean_region_outlives_predicate<'tcx>(
     pred: ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>,
-    cx: &mut DocContext<'tcx>,
 ) -> Option<WherePredicate> {
     let ty::OutlivesPredicate(a, b) = pred;
 
@@ -362,8 +359,10 @@ fn clean_region_outlives_predicate<'tcx>(
     }
 
     Some(WherePredicate::RegionPredicate {
-        lifetime: a.clean(cx).expect("failed to clean lifetime"),
-        bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
+        lifetime: clean_middle_region(a).expect("failed to clean lifetime"),
+        bounds: vec![GenericBound::Outlives(
+            clean_middle_region(b).expect("failed to clean bounds"),
+        )],
     })
 }
 
@@ -379,7 +378,9 @@ fn clean_type_outlives_predicate<'tcx>(
 
     Some(WherePredicate::BoundPredicate {
         ty: clean_middle_ty(ty, cx, None),
-        bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
+        bounds: vec![GenericBound::Outlives(
+            clean_middle_region(lt).expect("failed to clean lifetimes"),
+        )],
         bound_params: Vec::new(),
     })
 }
@@ -1592,7 +1593,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
         }
         ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
         ty::Ref(r, ty, mutbl) => BorrowedRef {
-            lifetime: r.clean(cx),
+            lifetime: clean_middle_region(r),
             mutability: mutbl,
             type_: Box::new(clean_middle_ty(ty, cx, None)),
         },
@@ -1639,7 +1640,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
 
             inline::record_extern_fqn(cx, did, ItemType::Trait);
 
-            let lifetime = reg.clean(cx);
+            let lifetime = clean_middle_region(*reg);
             let mut bounds = vec![];
 
             for did in dids {
@@ -1705,7 +1706,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
                     let trait_ref = match bound_predicate.skip_binder() {
                         ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
                         ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
-                            if let Some(r) = reg.clean(cx) {
+                            if let Some(r) = clean_middle_region(reg) {
                                 regions.push(GenericBound::Outlives(r));
                             }
                             return None;
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 621f70f0da986..43e71e90a6f5b 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -2,9 +2,9 @@ use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::render_macro_matchers::render_macro_matcher;
 use crate::clean::{
-    clean_middle_const, clean_middle_ty, inline, Clean, Crate, ExternalCrate, Generic, GenericArg,
-    GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, PathSegment, Primitive,
-    PrimitiveType, Type, TypeBinding, Visibility,
+    clean_middle_const, clean_middle_region, clean_middle_ty, inline, Clean, Crate, ExternalCrate,
+    Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, PathSegment,
+    Primitive, PrimitiveType, Type, TypeBinding, Visibility,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -86,7 +86,7 @@ pub(crate) fn substs_to_args<'tcx>(
         Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
     ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
         GenericArgKind::Lifetime(lt) => {
-            Some(GenericArg::Lifetime(lt.clean(cx).unwrap_or(Lifetime::elided())))
+            Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
         }
         GenericArgKind::Type(_) if skip_first => {
             skip_first = false;

From 3a6093ebca1071af04c2f4e92bbc4895123255c2 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Wed, 3 Aug 2022 11:38:18 +0200
Subject: [PATCH 06/10] remove Clean trait implementation for hir::IsAuto

---
 src/librustdoc/clean/mod.rs | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9e83021a5fbe4..07a1c9c3cd5b4 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -995,15 +995,6 @@ impl<'tcx> Clean<'tcx, FnRetTy> for hir::FnRetTy<'tcx> {
     }
 }
 
-impl<'tcx> Clean<'tcx, bool> for hir::IsAuto {
-    fn clean(&self, _: &mut DocContext<'tcx>) -> bool {
-        match *self {
-            hir::IsAuto::Yes => true,
-            hir::IsAuto::No => false,
-        }
-    }
-}
-
 impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> {
     fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
         let path = clean_path(self.path, cx);

From b5e1ac721f8aa7ac937db2d7bc1b61c17f306b51 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Wed, 3 Aug 2022 18:51:21 +0900
Subject: [PATCH 07/10] add regression test for #90871

---
 src/test/ui/closures/issue-90871.rs     |  5 +++++
 src/test/ui/closures/issue-90871.stderr | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 src/test/ui/closures/issue-90871.rs
 create mode 100644 src/test/ui/closures/issue-90871.stderr

diff --git a/src/test/ui/closures/issue-90871.rs b/src/test/ui/closures/issue-90871.rs
new file mode 100644
index 0000000000000..9c70bbc85acfa
--- /dev/null
+++ b/src/test/ui/closures/issue-90871.rs
@@ -0,0 +1,5 @@
+fn main() {
+    2: n([u8; || 1])
+    //~^ ERROR cannot find type `n` in this scope
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/closures/issue-90871.stderr b/src/test/ui/closures/issue-90871.stderr
new file mode 100644
index 0000000000000..1e102cc9805bd
--- /dev/null
+++ b/src/test/ui/closures/issue-90871.stderr
@@ -0,0 +1,23 @@
+error[E0412]: cannot find type `n` in this scope
+  --> $DIR/issue-90871.rs:2:8
+   |
+LL |     2: n([u8; || 1])
+   |        ^ expecting a type here because of type ascription
+
+error[E0308]: mismatched types
+  --> $DIR/issue-90871.rs:2:15
+   |
+LL |     2: n([u8; || 1])
+   |               ^^^^ expected `usize`, found closure
+   |
+   = note: expected type `usize`
+           found closure `[closure@$DIR/issue-90871.rs:2:15: 2:17]`
+help: use parentheses to call this closure
+   |
+LL |     2: n([u8; (|| 1)()])
+   |               +    +++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0412.
+For more information about an error, try `rustc --explain E0308`.

From 0548e8ed064623b5f5e72c79d7c9e4258f7cbc58 Mon Sep 17 00:00:00 2001
From: klensy <klensy@users.noreply.github.com>
Date: Wed, 3 Aug 2022 15:46:34 +0300
Subject: [PATCH 08/10] fix trailing whitespace in error message

---
 compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs      | 2 +-
 .../ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 5da260f980fbb..8c23756db3313 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -2736,7 +2736,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
                                 self.errors.push((
                                     e.span,
                                     format!(
-                                        "if the `for` loop runs 0 times, {} is not initialized ",
+                                        "if the `for` loop runs 0 times, {} is not initialized",
                                         self.name
                                     ),
                                 ));
diff --git a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr
index c08c93f361726..fc1a44c3ca04e 100644
--- a/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr
+++ b/src/test/ui/borrowck/borrowck-for-loop-uninitialized-binding.stderr
@@ -4,7 +4,7 @@ error[E0381]: used binding `x` is possibly-uninitialized
 LL |     let mut x: isize;
    |         ----- binding declared here but left uninitialized
 LL |     for _ in 0..0 { x = 10; }
-   |              ---- if the `for` loop runs 0 times, `x` is not initialized 
+   |              ---- if the `for` loop runs 0 times, `x` is not initialized
 LL |     return x;
    |            ^ `x` used here but it is possibly-uninitialized
 

From 939c2b63137e4b4f8c35d7cdc2b2d8bbb491e2dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 3 Aug 2022 09:29:29 -0700
Subject: [PATCH 09/10] Provide suggestion on missing `let` in binding
 statement

Fix #78907.
---
 compiler/rustc_ast_passes/src/feature_gate.rs | 30 +++++++++++++++++--
 src/test/ui/type/missing-let-in-binding.fixed |  5 ++++
 src/test/ui/type/missing-let-in-binding.rs    |  5 ++++
 .../ui/type/missing-let-in-binding.stderr     | 16 ++++++++++
 4 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 src/test/ui/type/missing-let-in-binding.fixed
 create mode 100644 src/test/ui/type/missing-let-in-binding.rs
 create mode 100644 src/test/ui/type/missing-let-in-binding.stderr

diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index ad9ed798e558b..6e33c261a03b0 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -2,7 +2,7 @@ use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
 use rustc_ast::{PatKind, RangeEnd, VariantData};
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, Applicability};
 use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, GateIssue};
 use rustc_session::parse::{feature_err, feature_err_issue};
@@ -577,6 +577,32 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         }
     }
 
+    fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
+        if let ast::StmtKind::Semi(expr) = &stmt.kind
+            && let ast::ExprKind::Assign(lhs, _, _) = &expr.kind
+            && let ast::ExprKind::Type(..) = lhs.kind
+            && self.sess.parse_sess.span_diagnostic.err_count() == 0
+            && !self.features.type_ascription
+            && !lhs.span.allows_unstable(sym::type_ascription)
+        {
+            // When we encounter a statement of the form `foo: Ty = val;`, this will emit a type
+            // ascription error, but the likely intention was to write a `let` statement. (#78907).
+            feature_err_issue(
+                &self.sess.parse_sess,
+                sym::type_ascription,
+                lhs.span,
+                GateIssue::Language,
+                "type ascription is experimental",
+            ).span_suggestion_verbose(
+                lhs.span.shrink_to_lo(),
+                "you might have meant to introduce a new binding",
+                "let ".to_string(),
+                Applicability::MachineApplicable,
+            ).emit();
+        }
+        visit::walk_stmt(self, stmt);
+    }
+
     fn visit_expr(&mut self, e: &'a ast::Expr) {
         match e.kind {
             ast::ExprKind::Box(_) => {
@@ -795,8 +821,6 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
     // checks if `#![feature]` has been used to enable any lang feature
     // does not check the same for lib features unless there's at least one
     // declared lang feature
-    use rustc_errors::Applicability;
-
     if !sess.opts.unstable_features.is_nightly_build() {
         let lang_features = &sess.features_untracked().declared_lang_features;
         if lang_features.len() == 0 {
diff --git a/src/test/ui/type/missing-let-in-binding.fixed b/src/test/ui/type/missing-let-in-binding.fixed
new file mode 100644
index 0000000000000..d1787688950ac
--- /dev/null
+++ b/src/test/ui/type/missing-let-in-binding.fixed
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let mut _foo: i32 = 1;
+    let _foo: i32 = 4; //~ ERROR type ascription is experimental
+}
diff --git a/src/test/ui/type/missing-let-in-binding.rs b/src/test/ui/type/missing-let-in-binding.rs
new file mode 100644
index 0000000000000..ca42f2e6eaccc
--- /dev/null
+++ b/src/test/ui/type/missing-let-in-binding.rs
@@ -0,0 +1,5 @@
+// run-rustfix
+fn main() {
+    let mut _foo: i32 = 1;
+    _foo: i32 = 4; //~ ERROR type ascription is experimental
+}
diff --git a/src/test/ui/type/missing-let-in-binding.stderr b/src/test/ui/type/missing-let-in-binding.stderr
new file mode 100644
index 0000000000000..12759c5096e23
--- /dev/null
+++ b/src/test/ui/type/missing-let-in-binding.stderr
@@ -0,0 +1,16 @@
+error[E0658]: type ascription is experimental
+  --> $DIR/missing-let-in-binding.rs:4:5
+   |
+LL |     _foo: i32 = 4;
+   |     ^^^^^^^^^
+   |
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+   = help: add `#![feature(type_ascription)]` to the crate attributes to enable
+help: you might have meant to introduce a new binding
+   |
+LL |     let _foo: i32 = 4;
+   |     +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.

From e86c128aa3f76e46131d52da1c7ee00921e72094 Mon Sep 17 00:00:00 2001
From: Ivan Markov <ivan.markov@gmail.com>
Date: Wed, 3 Aug 2022 19:07:25 +0000
Subject: [PATCH 10/10] FilesTimes support does not build for ESP-IDF

---
 library/std/src/sys/unix/fs.rs | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 41405cbf65703..b5cc8038ca44f 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -544,9 +544,11 @@ impl Default for FileTimes {
     fn default() -> Self {
         // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return
         // an error in `set_times`.
-        #[cfg(target_os = "redox")]
+        // ESP-IDF does not support `futimens` at all and the behavior for that OS is therefore
+        // the same as for Redox.
+        #[cfg(any(target_os = "redox", target_os = "espidf"))]
         let omit = libc::timespec { tv_sec: 0, tv_nsec: 0 };
-        #[cfg(not(target_os = "redox"))]
+        #[cfg(not(any(target_os = "redox", target_os = "espidf")))]
         let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ };
         Self([omit; 2])
     }
@@ -1077,8 +1079,10 @@ impl File {
 
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         cfg_if::cfg_if! {
-            if #[cfg(target_os = "redox")] {
+            if #[cfg(any(target_os = "redox", target_os = "espidf"))] {
                 // Redox doesn't appear to support `UTIME_OMIT`.
+                // ESP-IDF does not support `futimens` at all and the behavior for that OS is therefore
+                // the same as for Redox.
                 drop(times);
                 Err(io::const_io_error!(
                     io::ErrorKind::Unsupported,