Auto merge of #63498 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum

1.37.0 stable

This promotes beta to stable and backports a few PRs:

 - Avoid ICE when referencing desugared local binding in borrow error (#63051)
 - Don't access a static just for its size and alignment (#62982) via 331e09b143aebfcf82dc1f9b69b31ee0083cbf0b
diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index 18385f0..ab99057 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -30,6 +30,10 @@
 - bash: printenv | sort
   displayName: Show environment variables
 
+# Log the date, even on failure. Attempting to debug SSL certificate errors.
+- bash: date
+  displayName: Print out date (before build)
+
 - bash: |
     set -e
     df -h
@@ -198,3 +202,8 @@
   condition: variables['AWS_SECRET_ACCESS_KEY']
   continueOnError: true
   displayName: Upload CPU usage statistics
+
+# Log the date, even on failure. Attempting to debug SSL certificate errors.
+- bash: date
+  continueOnError: true
+  displayName: Print out date (after build)
diff --git a/src/ci/run.sh b/src/ci/run.sh
index e5e0e6c..f19bd4e 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -45,7 +45,7 @@
 #
 # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable`
 #        either automatically or manually.
-export RUST_RELEASE_CHANNEL=beta
+export RUST_RELEASE_CHANNEL=stable
 if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index f23cffe..b9cd1f0 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -1116,19 +1116,18 @@
                 bug!("try_report_cannot_return_reference_to_local: not a local")
             };
             match self.body.local_kind(local) {
-                LocalKind::ReturnPointer | LocalKind::Temp => {
-                    (
-                        "temporary value".to_string(),
-                        "temporary value created here".to_string(),
-                    )
-                }
-                LocalKind::Arg => {
-                    (
-                        "function parameter".to_string(),
-                        "function parameter borrowed here".to_string(),
-                    )
-                },
-                LocalKind::Var => bug!("local variable without a name"),
+                LocalKind::ReturnPointer | LocalKind::Temp => (
+                    "temporary value".to_string(),
+                    "temporary value created here".to_string(),
+                ),
+                LocalKind::Arg => (
+                    "function parameter".to_string(),
+                    "function parameter borrowed here".to_string(),
+                ),
+                LocalKind::Var => (
+                    "local binding".to_string(),
+                    "local binding introduced here".to_string(),
+                ),
             }
         };
 
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 4eb95f2..9126393 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -54,6 +54,11 @@
         k: K,
         vacant: impl FnOnce() -> Result<V, E>
     ) -> Result<&mut V, E>;
+
+    /// Read-only lookup.
+    fn get(&self, k: K) -> Option<&V> {
+        self.get_or(k, || Err(())).ok()
+    }
 }
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index c3eec67..56a0e14 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -492,13 +492,18 @@
         id: AllocId,
         liveness: AllocCheck,
     ) -> InterpResult<'static, (Size, Align)> {
-        if let Ok(alloc) = self.get(id) {
+        // # Regular allocations
+        // Don't use `self.get` here as that will
+        // a) cause cycles in case `id` refers to a static
+        // b) duplicate a static's allocation in miri
+        if let Some((_, alloc)) = self.alloc_map.get(id) {
             return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
         }
-        // can't do this in the match argument, we may get cycle errors since the lock would get
-        // dropped after the match.
+
+        // # Statics and function pointers
+        // Can't do this in the match argument, we may get cycle errors since the lock would
+        // be held throughout the match.
         let alloc = self.tcx.alloc_map.lock().get(id);
-        // Could also be a fn ptr or extern static
         match alloc {
             Some(GlobalAlloc::Function(..)) => {
                 if let AllocCheck::Dereferencable = liveness {
@@ -507,28 +512,26 @@
                 } else {
                     Ok((Size::ZERO, Align::from_bytes(1).unwrap()))
                 }
-            }
-            // `self.get` would also work, but can cause cycles if a static refers to itself
+            },
             Some(GlobalAlloc::Static(did)) => {
-                // The only way `get` couldn't have worked here is if this is an extern static
-                assert!(self.tcx.is_foreign_item(did));
-                // Use size and align of the type
+                // Use size and align of the type.
                 let ty = self.tcx.type_of(did);
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
                 Ok((layout.size, layout.align.abi))
-            }
-            _ => {
-                if let Ok(alloc) = self.get(id) {
-                    Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align))
-                }
-                else if let AllocCheck::MaybeDead = liveness {
-                    // Deallocated pointers are allowed, we should be able to find
-                    // them in the map.
-                    Ok(*self.dead_alloc_map.get(&id)
-                        .expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
-                } else {
-                    err!(DanglingPointerDeref)
-                }
+            },
+            Some(GlobalAlloc::Memory(alloc)) =>
+                // Need to duplicate the logic here, because the global allocations have
+                // different associated types than the interpreter-local ones.
+                Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
+            // The rest must be dead.
+            None => if let AllocCheck::MaybeDead = liveness {
+                // Deallocated pointers are allowed, we should be able to find
+                // them in the map.
+                Ok(*self.dead_alloc_map.get(&id)
+                    .expect("deallocated pointers should all be recorded in \
+                            `dead_alloc_map`"))
+            } else {
+                err!(DanglingPointerDeref)
             },
         }
     }
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.rs b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
new file mode 100644
index 0000000..b2dcd54
--- /dev/null
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.rs
@@ -0,0 +1,33 @@
+// To avoid leaking the names of local bindings from expressions like for loops, #60984
+// explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would
+// trigger an ICE. Before this change, this file's output would be:
+// ```
+// error[E0515]: cannot return value referencing local variable `__next`
+//   --> return-local-binding-from-desugaring.rs:LL:CC
+//    |
+// LL |     for ref x in xs {
+//    |         ----- `__next` is borrowed here
+// ...
+// LL |     result
+//    |     ^^^^^^ returns a value referencing data owned by the current function
+// ```
+// FIXME: ideally `LocalKind` would carry more information to more accurately explain the problem.
+
+use std::collections::HashMap;
+use std::hash::Hash;
+
+fn group_by<I, F, T>(xs: &mut I, f: F) -> HashMap<T, Vec<&I::Item>>
+where
+    I: Iterator,
+    F: Fn(&I::Item) -> T,
+    T: Eq + Hash,
+{
+    let mut result = HashMap::new();
+    for ref x in xs {
+        let key = f(x);
+        result.entry(key).or_insert(Vec::new()).push(x);
+    }
+    result //~ ERROR cannot return value referencing local binding
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
new file mode 100644
index 0000000..293dbe6
--- /dev/null
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.stderr
@@ -0,0 +1,12 @@
+error[E0515]: cannot return value referencing local binding
+  --> $DIR/return-local-binding-from-desugaring.rs:30:5
+   |
+LL |     for ref x in xs {
+   |                  -- local binding introduced here
+...
+LL |     result
+   |     ^^^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
diff --git a/src/test/ui/consts/static-cycle-error.rs b/src/test/ui/consts/static-cycle-error.rs
new file mode 100644
index 0000000..8e69d3e
--- /dev/null
+++ b/src/test/ui/consts/static-cycle-error.rs
@@ -0,0 +1,11 @@
+// compile-pass
+
+struct Foo {
+    foo: Option<&'static Foo>
+}
+
+static FOO: Foo = Foo {
+    foo: Some(&FOO),
+};
+
+fn main() {}