diff --git a/Cargo.lock b/Cargo.lock
index 9485e1674448eac3473f22bd65174768064caa47..6d9e18e6488dadbd03e3cc78bb1e8529b84a5f3c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -217,10 +217,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "autocfg"
-version = "0.1.6"
-
 [[package]]
 name = "autocfg"
 version = "1.0.1"
@@ -363,7 +359,7 @@ version = "0.1.0"
 dependencies = [
  "bits_client",
  "comedy",
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
  "libc",
  "log",
  "moz_task",
@@ -434,7 +430,7 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b8e3ff9db740167616e528c509b3618046fc05d337f8f3182d300f4aa977d2bb"
 dependencies = [
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
  "jobserver",
  "num_cpus",
 ]
@@ -521,7 +517,7 @@ version = "0.0.1"
 dependencies = [
  "base64 0.10.1",
  "byteorder",
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
  "cstr",
  "log",
  "malloc_size_of_derive",
@@ -863,40 +859,42 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
 dependencies = [
- "crossbeam-utils 0.7.0",
+ "crossbeam-utils 0.7.2",
  "maybe-uninit",
 ]
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
+checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
 dependencies = [
  "cfg-if 1.0.0",
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
+checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
 dependencies = [
  "crossbeam-epoch",
- "crossbeam-utils 0.7.0",
+ "crossbeam-utils 0.7.2",
+ "maybe-uninit",
 ]
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
+checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
 dependencies = [
- "autocfg 0.1.6",
+ "autocfg",
  "cfg-if 0.1.10",
- "crossbeam-utils 0.7.0",
+ "crossbeam-utils 0.7.2",
  "lazy_static",
+ "maybe-uninit",
  "memoffset",
  "scopeguard",
 ]
@@ -907,14 +905,14 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
 dependencies = [
- "crossbeam-utils 0.6.5",
+ "crossbeam-utils 0.6.6",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.6.5"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
+checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
 dependencies = [
  "cfg-if 0.1.10",
  "lazy_static",
@@ -922,22 +920,21 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.7.0"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
+checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
 dependencies = [
- "autocfg 0.1.6",
+ "autocfg",
  "cfg-if 0.1.10",
  "lazy_static",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.1"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
+checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
 dependencies = [
- "autocfg 1.0.1",
  "cfg-if 1.0.0",
  "lazy_static",
 ]
@@ -2085,7 +2082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c8e24825d3123194a212e3daf8ddac150713cec4f1e126dc3c12ba207f0b5d77"
 dependencies = [
  "chrono",
- "crossbeam-channel 0.5.0",
+ "crossbeam-channel 0.5.1",
  "glean-core",
  "inherent",
  "log",
@@ -2437,7 +2434,7 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
 dependencies = [
- "autocfg 1.0.1",
+ "autocfg",
  "hashbrown",
 ]
 
@@ -2667,7 +2664,7 @@ name = "kvstore"
 version = "0.1.0"
 dependencies = [
  "atomic_refcell",
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
  "cstr",
  "lazy_static",
  "libc",
@@ -3089,7 +3086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
 dependencies = [
  "adler",
- "autocfg 1.0.1",
+ "autocfg",
 ]
 
 [[package]]
@@ -3524,7 +3521,7 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
 dependencies = [
- "autocfg 1.0.1",
+ "autocfg",
  "num-integer",
  "num-traits",
 ]
@@ -3546,7 +3543,7 @@ version = "0.1.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
 dependencies = [
- "autocfg 1.0.1",
+ "autocfg",
  "num-traits",
 ]
 
@@ -3556,7 +3553,7 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
 dependencies = [
- "autocfg 1.0.1",
+ "autocfg",
 ]
 
 [[package]]
@@ -4149,7 +4146,7 @@ version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dcf6960dc9a5b4ee8d3e4c5787b4a112a8818e0290a42ff664ad60692fdf2032"
 dependencies = [
- "autocfg 1.0.1",
+ "autocfg",
  "crossbeam-deque",
  "either",
  "rayon-core",
@@ -4163,7 +4160,7 @@ checksum = "e8c4fec834fb6e6d2dd5eece3c7b432a52f0ba887cf40e595190c4107edc08bf"
 dependencies = [
  "crossbeam-channel 0.4.4",
  "crossbeam-deque",
- "crossbeam-utils 0.7.0",
+ "crossbeam-utils 0.7.2",
  "lazy_static",
  "num_cpus",
 ]
@@ -4387,7 +4384,7 @@ checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
 dependencies = [
  "base64 0.10.1",
  "blake2b_simd",
- "crossbeam-utils 0.6.5",
+ "crossbeam-utils 0.6.6",
 ]
 
 [[package]]
@@ -5269,7 +5266,7 @@ version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab"
 dependencies = [
- "crossbeam-utils 0.6.5",
+ "crossbeam-utils 0.6.6",
  "futures 0.1.29",
 ]
 
@@ -5331,7 +5328,7 @@ checksum = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c"
 dependencies = [
  "crossbeam-deque",
  "crossbeam-queue",
- "crossbeam-utils 0.6.5",
+ "crossbeam-utils 0.6.6",
  "futures 0.1.29",
  "lazy_static",
  "log",
@@ -5346,7 +5343,7 @@ version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e"
 dependencies = [
- "crossbeam-utils 0.6.5",
+ "crossbeam-utils 0.6.6",
  "futures 0.1.29",
  "slab",
  "tokio-executor",
@@ -5786,7 +5783,7 @@ dependencies = [
  "byteorder",
  "core-foundation",
  "core-graphics",
- "crossbeam-channel 0.5.0",
+ "crossbeam-channel 0.5.1",
  "derive_more",
  "euclid",
  "malloc_size_of_derive",
@@ -6037,7 +6034,7 @@ dependencies = [
 name = "xulstore"
 version = "0.1.0"
 dependencies = [
- "crossbeam-utils 0.8.1",
+ "crossbeam-utils 0.8.5",
  "cstr",
  "libc",
  "log",
diff --git a/Cargo.toml b/Cargo.toml
index ef1cbabbce6a143d11dde20161b405263f29ac6e..32119df16e3120872b5b47b0c9f7a60d7cf7e28a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -97,10 +97,6 @@ rev = "824fa69756523f2b6d49029fe25de94130b1f144"
 [patch.crates-io.autocfg]
 path = "third_party/rust/autocfg"
 
-[patch.crates-io.autocfg01]
-path = "third_party/rust/autocfg-0.1.6"
-package = "autocfg"
-
 # Patch mio 0.6 to use winapi 0.3 and miow 0.3, getting rid of winapi 0.2.
 # There is not going to be new version of mio 0.6, mio now being >= 0.7.11.
 [patch.crates-io.mio]
diff --git a/third_party/rust/autocfg-0.1.6/.cargo-checksum.json b/third_party/rust/autocfg-0.1.6/.cargo-checksum.json
deleted file mode 100644
index e7bd53b6e17f805b09b87e925ea4f313da7097de..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.lock":"461e5e87b13d7faf25813b08b5003060c39d8af0953f30d5b80ae0926c888022","Cargo.toml":"1eded5c9954b3bb92bb2c7403e026198e66a2a42199db06fc9cafddc8d1fd677","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"ba9a1621483e0b9f017f07c282d00d5cf3a2d8660cca6df6b14941319d748953","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"411d8dbc48ab0f67cb10243f1e16b235407818c96556c838182e4004da995dff","src/tests.rs":"0b1353344e832553d328c47f1639ced877b5dff70fd2024d84130bd1c33eee07","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3"},"package":"b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"}
\ No newline at end of file
diff --git a/third_party/rust/autocfg-0.1.6/Cargo.lock b/third_party/rust/autocfg-0.1.6/Cargo.lock
deleted file mode 100644
index 4f899ca2928957bd275d39bb2f86719f4456c9f6..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/Cargo.lock
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "autocfg"
-version = "0.1.6"
-
diff --git a/third_party/rust/autocfg-0.1.6/Cargo.toml b/third_party/rust/autocfg-0.1.6/Cargo.toml
deleted file mode 100644
index 4453db3d9817dbdf872fd1ab2ac009208cd78e7f..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "autocfg"
-version = "0.1.6"
-authors = ["Josh Stone <cuviper@gmail.com>"]
-description = "Automatic cfg for Rust compiler features"
-readme = "README.md"
-keywords = ["rustc", "build", "autoconf"]
-categories = ["development-tools::build-utils"]
-license = "Apache-2.0/MIT"
-repository = "https://github.com/cuviper/autocfg"
-
-[dependencies]
diff --git a/third_party/rust/autocfg-0.1.6/README.md b/third_party/rust/autocfg-0.1.6/README.md
deleted file mode 100644
index 40004a88e80533f35c9c7650da99e8a84b88ae37..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-autocfg
-=======
-
-[![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg)
-[![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg)
-![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg)
-[![Travis Status](https://travis-ci.org/cuviper/autocfg.svg?branch=master)](https://travis-ci.org/cuviper/autocfg)
-
-A Rust library for build scripts to automatically configure code based on
-compiler support.  Code snippets are dynamically tested to see if the `rustc`
-will accept them, rather than hard-coding specific version support.
-
-
-## Usage
-
-Add this to your `Cargo.toml`:
-
-```toml
-[build-dependencies]
-autocfg = "0.1"
-```
-
-Then use it in your `build.rs` script to detect compiler features.  For
-example, to test for 128-bit integer support, it might look like:
-
-```rust
-extern crate autocfg;
-
-fn main() {
-    let ac = autocfg::new();
-    ac.emit_has_type("i128");
-
-    // (optional) We don't need to rerun for anything external.
-    autocfg::rerun_path(file!());
-}
-```
-
-If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
-for Cargo, which translates to Rust arguments `--cfg has_i128`.  Then in the
-rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
-should only be used when the compiler supports it.
-
-
-## Release Notes
-
-- 0.1.6 (2019-08-19)
-  - Add `probe`/`emit_sysroot_crate`, by @leo60228
-
-- 0.1.5 (2019-07-16)
-  - Mask some warnings from newer rustc.
-
-- 0.1.4 (2019-05-22)
-  - Relax `std`/`no_std` probing to a warning instead of an error.
-  - Improve `rustc` bootstrap compatibility.
-
-- 0.1.3 (2019-05-21)
-  - Auto-detects if `#![no_std]` is needed for the `$TARGET`
-
-- 0.1.2 (2019-01-16)
-  - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`
-  - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`
-
-
-## Minimum Rust version policy
-
-This crate's minimum supported `rustc` version is `1.0.0`.  Compatibility is
-its entire reason for existence, so this crate will be extremely conservative
-about raising this requirement.  If this is ever deemed necessary, it will be
-treated as a major breaking change for semver purposes.
-
-
-## License
-
-This project is licensed under either of
-
- * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
-   http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license ([LICENSE-MIT](LICENSE-MIT) or
-   http://opensource.org/licenses/MIT)
-
-at your option.
diff --git a/third_party/rust/autocfg-0.1.6/examples/integers.rs b/third_party/rust/autocfg-0.1.6/examples/integers.rs
deleted file mode 100644
index 23d4cba6ee3e96e8ee90d701d035478a73841ecc..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/examples/integers.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    // Normally, cargo will set `OUT_DIR` for build scripts.
-    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
-    for i in 3..8 {
-        ac.emit_has_type(&format!("i{}", 1 << i));
-    }
-}
diff --git a/third_party/rust/autocfg-0.1.6/examples/paths.rs b/third_party/rust/autocfg-0.1.6/examples/paths.rs
deleted file mode 100644
index b7a6ca7a25f7b35ae2e535ccc16cc1a53339f90f..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/examples/paths.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    // Normally, cargo will set `OUT_DIR` for build scripts.
-    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
-
-    // since ancient times...
-    ac.emit_has_path("std::vec::Vec");
-    ac.emit_path_cfg("std::vec::Vec", "has_vec");
-
-    // rustc 1.10.0
-    ac.emit_has_path("std::panic::PanicInfo");
-    ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info");
-
-    // rustc 1.20.0
-    ac.emit_has_path("std::mem::ManuallyDrop");
-    ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop");
-
-    // rustc 1.25.0
-    ac.emit_has_path("std::ptr::NonNull");
-    ac.emit_path_cfg("std::ptr::NonNull", "has_non_null");
-}
diff --git a/third_party/rust/autocfg-0.1.6/examples/traits.rs b/third_party/rust/autocfg-0.1.6/examples/traits.rs
deleted file mode 100644
index c1ca00385cd403b9fa0bcca1f8c746d419ed22ce..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/examples/traits.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    // Normally, cargo will set `OUT_DIR` for build scripts.
-    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
-
-    // since ancient times...
-    ac.emit_has_trait("std::ops::Add");
-    ac.emit_trait_cfg("std::ops::Add", "has_ops");
-
-    // trait parameters have to be provided
-    ac.emit_has_trait("std::borrow::Borrow<str>");
-    ac.emit_trait_cfg("std::borrow::Borrow<str>", "has_borrow");
-
-    // rustc 1.8.0
-    ac.emit_has_trait("std::ops::AddAssign");
-    ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops");
-
-    // rustc 1.12.0
-    ac.emit_has_trait("std::iter::Sum");
-    ac.emit_trait_cfg("std::iter::Sum", "has_sum");
-
-    // rustc 1.28.0
-    ac.emit_has_trait("std::alloc::GlobalAlloc");
-    ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc");
-}
diff --git a/third_party/rust/autocfg-0.1.6/examples/versions.rs b/third_party/rust/autocfg-0.1.6/examples/versions.rs
deleted file mode 100644
index 992919b7c642806e52ae35db49a9b3e3dd787ace..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/examples/versions.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    // Normally, cargo will set `OUT_DIR` for build scripts.
-    let ac = autocfg::AutoCfg::with_dir("target").unwrap();
-    for i in 0..100 {
-        ac.emit_rustc_version(1, i);
-    }
-}
diff --git a/third_party/rust/autocfg-0.1.6/src/error.rs b/third_party/rust/autocfg-0.1.6/src/error.rs
deleted file mode 100644
index 4624835451b05ce906f295546fb198481042abd9..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/src/error.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-use std::error;
-use std::fmt;
-use std::io;
-use std::num;
-use std::str;
-
-/// A common error type for the `autocfg` crate.
-#[derive(Debug)]
-pub struct Error {
-    kind: ErrorKind,
-}
-
-impl error::Error for Error {
-    fn description(&self) -> &str {
-        "AutoCfg error"
-    }
-
-    fn cause(&self) -> Option<&error::Error> {
-        match self.kind {
-            ErrorKind::Io(ref e) => Some(e),
-            ErrorKind::Num(ref e) => Some(e),
-            ErrorKind::Utf8(ref e) => Some(e),
-            ErrorKind::Other(_) => None,
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        match self.kind {
-            ErrorKind::Io(ref e) => e.fmt(f),
-            ErrorKind::Num(ref e) => e.fmt(f),
-            ErrorKind::Utf8(ref e) => e.fmt(f),
-            ErrorKind::Other(s) => s.fmt(f),
-        }
-    }
-}
-
-#[derive(Debug)]
-enum ErrorKind {
-    Io(io::Error),
-    Num(num::ParseIntError),
-    Utf8(str::Utf8Error),
-    Other(&'static str),
-}
-
-pub fn from_io(e: io::Error) -> Error {
-    Error {
-        kind: ErrorKind::Io(e),
-    }
-}
-
-pub fn from_num(e: num::ParseIntError) -> Error {
-    Error {
-        kind: ErrorKind::Num(e),
-    }
-}
-
-pub fn from_utf8(e: str::Utf8Error) -> Error {
-    Error {
-        kind: ErrorKind::Utf8(e),
-    }
-}
-
-pub fn from_str(s: &'static str) -> Error {
-    Error {
-        kind: ErrorKind::Other(s),
-    }
-}
diff --git a/third_party/rust/autocfg-0.1.6/src/lib.rs b/third_party/rust/autocfg-0.1.6/src/lib.rs
deleted file mode 100644
index ea4ed03ca72016408741ccace64dbdf2ab22f85b..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/src/lib.rs
+++ /dev/null
@@ -1,329 +0,0 @@
-//! A Rust library for build scripts to automatically configure code based on
-//! compiler support.  Code snippets are dynamically tested to see if the `rustc`
-//! will accept them, rather than hard-coding specific version support.
-//!
-//!
-//! ## Usage
-//!
-//! Add this to your `Cargo.toml`:
-//!
-//! ```toml
-//! [build-dependencies]
-//! autocfg = "0.1"
-//! ```
-//!
-//! Then use it in your `build.rs` script to detect compiler features.  For
-//! example, to test for 128-bit integer support, it might look like:
-//!
-//! ```rust
-//! extern crate autocfg;
-//!
-//! fn main() {
-//! #   // Normally, cargo will set `OUT_DIR` for build scripts.
-//! #   std::env::set_var("OUT_DIR", "target");
-//!     let ac = autocfg::new();
-//!     ac.emit_has_type("i128");
-//!
-//!     // (optional) We don't need to rerun for anything external.
-//!     autocfg::rerun_path(file!());
-//! }
-//! ```
-//!
-//! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line
-//! for Cargo, which translates to Rust arguments `--cfg has_i128`.  Then in the
-//! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that
-//! should only be used when the compiler supports it.
-
-#![deny(missing_debug_implementations)]
-#![deny(missing_docs)]
-// allow future warnings that can't be fixed while keeping 1.0 compatibility
-#![allow(unknown_lints)]
-#![allow(bare_trait_objects)]
-#![allow(ellipsis_inclusive_range_patterns)]
-#![allow(warnings)]
-
-use std::env;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{stderr, Write};
-use std::path::PathBuf;
-use std::process::{Command, Stdio};
-#[allow(deprecated)]
-use std::sync::atomic::ATOMIC_USIZE_INIT;
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-mod error;
-pub use error::Error;
-
-mod version;
-use version::Version;
-
-#[cfg(test)]
-mod tests;
-
-/// Helper to detect compiler features for `cfg` output in build scripts.
-#[derive(Clone, Debug)]
-pub struct AutoCfg {
-    out_dir: PathBuf,
-    rustc: PathBuf,
-    rustc_version: Version,
-    target: Option<OsString>,
-    no_std: bool,
-}
-
-/// Writes a config flag for rustc on standard out.
-///
-/// This looks like: `cargo:rustc-cfg=CFG`
-///
-/// Cargo will use this in arguments to rustc, like `--cfg CFG`.
-pub fn emit(cfg: &str) {
-    println!("cargo:rustc-cfg={}", cfg);
-}
-
-/// Writes a line telling Cargo to rerun the build script if `path` changes.
-///
-/// This looks like: `cargo:rerun-if-changed=PATH`
-///
-/// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0.  Earlier
-/// versions of cargo will simply ignore the directive.
-pub fn rerun_path(path: &str) {
-    println!("cargo:rerun-if-changed={}", path);
-}
-
-/// Writes a line telling Cargo to rerun the build script if the environment
-/// variable `var` changes.
-///
-/// This looks like: `cargo:rerun-if-env-changed=VAR`
-///
-/// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0.  Earlier
-/// versions of cargo will simply ignore the directive.
-pub fn rerun_env(var: &str) {
-    println!("cargo:rerun-if-env-changed={}", var);
-}
-
-/// Create a new `AutoCfg` instance.
-///
-/// # Panics
-///
-/// Panics if `AutoCfg::new()` returns an error.
-pub fn new() -> AutoCfg {
-    AutoCfg::new().unwrap()
-}
-
-impl AutoCfg {
-    /// Create a new `AutoCfg` instance.
-    ///
-    /// # Common errors
-    ///
-    /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
-    /// - The version output from `rustc` can't be parsed.
-    /// - `OUT_DIR` is not set in the environment, or is not a writable directory.
-    ///
-    pub fn new() -> Result<Self, Error> {
-        match env::var_os("OUT_DIR") {
-            Some(d) => Self::with_dir(d),
-            None => Err(error::from_str("no OUT_DIR specified!")),
-        }
-    }
-
-    /// Create a new `AutoCfg` instance with the specified output directory.
-    ///
-    /// # Common errors
-    ///
-    /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`.
-    /// - The version output from `rustc` can't be parsed.
-    /// - `dir` is not a writable directory.
-    ///
-    pub fn with_dir<T: Into<PathBuf>>(dir: T) -> Result<Self, Error> {
-        let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
-        let rustc: PathBuf = rustc.into();
-        let rustc_version = try!(Version::from_rustc(&rustc));
-
-        // Sanity check the output directory
-        let dir = dir.into();
-        let meta = try!(fs::metadata(&dir).map_err(error::from_io));
-        if !meta.is_dir() || meta.permissions().readonly() {
-            return Err(error::from_str("output path is not a writable directory"));
-        }
-
-        let mut ac = AutoCfg {
-            out_dir: dir,
-            rustc: rustc,
-            rustc_version: rustc_version,
-            target: env::var_os("TARGET"),
-            no_std: false,
-        };
-
-        // Sanity check with and without `std`.
-        if !ac.probe("").unwrap_or(false) {
-            ac.no_std = true;
-            if !ac.probe("").unwrap_or(false) {
-                // Neither worked, so assume nothing...
-                ac.no_std = false;
-                let warning = b"warning: autocfg could not probe for `std`\n";
-                stderr().write_all(warning).ok();
-            }
-        }
-        Ok(ac)
-    }
-
-    /// Test whether the current `rustc` reports a version greater than
-    /// or equal to "`major`.`minor`".
-    pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool {
-        self.rustc_version >= Version::new(major, minor, 0)
-    }
-
-    /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`,
-    /// if the current `rustc` is at least that version.
-    pub fn emit_rustc_version(&self, major: usize, minor: usize) {
-        if self.probe_rustc_version(major, minor) {
-            emit(&format!("rustc_{}_{}", major, minor));
-        }
-    }
-
-    fn probe<T: AsRef<[u8]>>(&self, code: T) -> Result<bool, Error> {
-        #[allow(deprecated)]
-        static ID: AtomicUsize = ATOMIC_USIZE_INIT;
-
-        let id = ID.fetch_add(1, Ordering::Relaxed);
-        let mut command = Command::new(&self.rustc);
-        command
-            .arg("--crate-name")
-            .arg(format!("probe{}", id))
-            .arg("--crate-type=lib")
-            .arg("--out-dir")
-            .arg(&self.out_dir)
-            .arg("--emit=llvm-ir");
-
-        if let Some(target) = self.target.as_ref() {
-            command.arg("--target").arg(target);
-        }
-
-        command.arg("-").stdin(Stdio::piped()).stderr(Stdio::null());
-        let mut child = try!(command.spawn().map_err(error::from_io));
-        let mut stdin = child.stdin.take().expect("rustc stdin");
-
-        if self.no_std {
-            try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io));
-        }
-        try!(stdin.write_all(code.as_ref()).map_err(error::from_io));
-        drop(stdin);
-
-        let status = try!(child.wait().map_err(error::from_io));
-        Ok(status.success())
-    }
-
-    /// Tests whether the given sysroot crate can be used.
-    ///
-    /// The test code is subject to change, but currently looks like:
-    ///
-    /// ```ignore
-    /// extern crate CRATE as probe;
-    /// ```
-    pub fn probe_sysroot_crate(&self, name: &str) -> bool {
-        self.probe(format!("extern crate {} as probe;", name)) // `as _` wasn't stabilized until Rust 1.33
-            .unwrap_or(false)
-    }
-
-    /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true.
-    pub fn emit_sysroot_crate(&self, name: &str) {
-        if self.probe_sysroot_crate(name) {
-            emit(&format!("has_{}", mangle(name)));
-        }
-    }
-
-    /// Tests whether the given path can be used.
-    ///
-    /// The test code is subject to change, but currently looks like:
-    ///
-    /// ```ignore
-    /// pub use PATH;
-    /// ```
-    pub fn probe_path(&self, path: &str) -> bool {
-        self.probe(format!("pub use {};", path)).unwrap_or(false)
-    }
-
-    /// Emits a config value `has_PATH` if `probe_path` returns true.
-    ///
-    /// Any non-identifier characters in the `path` will be replaced with
-    /// `_` in the generated config value.
-    pub fn emit_has_path(&self, path: &str) {
-        if self.probe_path(path) {
-            emit(&format!("has_{}", mangle(path)));
-        }
-    }
-
-    /// Emits the given `cfg` value if `probe_path` returns true.
-    pub fn emit_path_cfg(&self, path: &str, cfg: &str) {
-        if self.probe_path(path) {
-            emit(cfg);
-        }
-    }
-
-    /// Tests whether the given trait can be used.
-    ///
-    /// The test code is subject to change, but currently looks like:
-    ///
-    /// ```ignore
-    /// pub trait Probe: TRAIT + Sized {}
-    /// ```
-    pub fn probe_trait(&self, name: &str) -> bool {
-        self.probe(format!("pub trait Probe: {} + Sized {{}}", name))
-            .unwrap_or(false)
-    }
-
-    /// Emits a config value `has_TRAIT` if `probe_trait` returns true.
-    ///
-    /// Any non-identifier characters in the trait `name` will be replaced with
-    /// `_` in the generated config value.
-    pub fn emit_has_trait(&self, name: &str) {
-        if self.probe_trait(name) {
-            emit(&format!("has_{}", mangle(name)));
-        }
-    }
-
-    /// Emits the given `cfg` value if `probe_trait` returns true.
-    pub fn emit_trait_cfg(&self, name: &str, cfg: &str) {
-        if self.probe_trait(name) {
-            emit(cfg);
-        }
-    }
-
-    /// Tests whether the given type can be used.
-    ///
-    /// The test code is subject to change, but currently looks like:
-    ///
-    /// ```ignore
-    /// pub type Probe = TYPE;
-    /// ```
-    pub fn probe_type(&self, name: &str) -> bool {
-        self.probe(format!("pub type Probe = {};", name))
-            .unwrap_or(false)
-    }
-
-    /// Emits a config value `has_TYPE` if `probe_type` returns true.
-    ///
-    /// Any non-identifier characters in the type `name` will be replaced with
-    /// `_` in the generated config value.
-    pub fn emit_has_type(&self, name: &str) {
-        if self.probe_type(name) {
-            emit(&format!("has_{}", mangle(name)));
-        }
-    }
-
-    /// Emits the given `cfg` value if `probe_type` returns true.
-    pub fn emit_type_cfg(&self, name: &str, cfg: &str) {
-        if self.probe_type(name) {
-            emit(cfg);
-        }
-    }
-}
-
-fn mangle(s: &str) -> String {
-    s.chars()
-        .map(|c| match c {
-            'A'...'Z' | 'a'...'z' | '0'...'9' => c,
-            _ => '_',
-        })
-        .collect()
-}
diff --git a/third_party/rust/autocfg-0.1.6/src/tests.rs b/third_party/rust/autocfg-0.1.6/src/tests.rs
deleted file mode 100644
index 304d989bcb408221b1b074acc6a7edd2f3e2a2ef..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/src/tests.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-use super::AutoCfg;
-
-impl AutoCfg {
-    fn core_std(&self, path: &str) -> String {
-        let krate = if self.no_std { "core" } else { "std" };
-        format!("{}::{}", krate, path)
-    }
-}
-
-#[test]
-fn autocfg_version() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    println!("version: {:?}", ac.rustc_version);
-    assert!(ac.probe_rustc_version(1, 0));
-}
-
-#[test]
-fn version_cmp() {
-    use super::version::Version;
-    let v123 = Version::new(1, 2, 3);
-
-    assert!(Version::new(1, 0, 0) < v123);
-    assert!(Version::new(1, 2, 2) < v123);
-    assert!(Version::new(1, 2, 3) == v123);
-    assert!(Version::new(1, 2, 4) > v123);
-    assert!(Version::new(1, 10, 0) > v123);
-    assert!(Version::new(2, 0, 0) > v123);
-}
-
-#[test]
-fn probe_add() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    let add = ac.core_std("ops::Add");
-    let add_rhs = ac.core_std("ops::Add<i32>");
-    let add_rhs_output = ac.core_std("ops::Add<i32, Output = i32>");
-    assert!(ac.probe_path(&add));
-    assert!(ac.probe_trait(&add));
-    assert!(ac.probe_trait(&add_rhs));
-    assert!(ac.probe_trait(&add_rhs_output));
-    assert!(ac.probe_type(&add_rhs_output));
-}
-
-#[test]
-fn probe_as_ref() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    let as_ref = ac.core_std("convert::AsRef");
-    let as_ref_str = ac.core_std("convert::AsRef<str>");
-    assert!(ac.probe_path(&as_ref));
-    assert!(ac.probe_trait(&as_ref_str));
-    assert!(ac.probe_type(&as_ref_str));
-}
-
-#[test]
-fn probe_i128() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    let missing = !ac.probe_rustc_version(1, 26);
-    let i128_path = ac.core_std("i128");
-    assert!(missing ^ ac.probe_path(&i128_path));
-    assert!(missing ^ ac.probe_type("i128"));
-}
-
-#[test]
-fn probe_sum() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    let missing = !ac.probe_rustc_version(1, 12);
-    let sum = ac.core_std("iter::Sum");
-    let sum_i32 = ac.core_std("iter::Sum<i32>");
-    assert!(missing ^ ac.probe_path(&sum));
-    assert!(missing ^ ac.probe_trait(&sum));
-    assert!(missing ^ ac.probe_trait(&sum_i32));
-    assert!(missing ^ ac.probe_type(&sum_i32));
-}
-
-#[test]
-fn probe_std() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    assert_eq!(ac.probe_sysroot_crate("std"), !ac.no_std);
-}
-
-#[test]
-fn probe_alloc() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    let missing = !ac.probe_rustc_version(1, 36);
-    assert!(missing ^ ac.probe_sysroot_crate("alloc"));
-}
-
-#[test]
-fn probe_bad_sysroot_crate() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    assert!(!ac.probe_sysroot_crate("doesnt_exist"));
-}
-
-#[test]
-fn probe_no_std() {
-    let ac = AutoCfg::with_dir("target").unwrap();
-    assert!(ac.probe_type("i32"));
-    assert!(ac.probe_type("[i32]"));
-    assert_eq!(ac.probe_type("Vec<i32>"), !ac.no_std);
-}
diff --git a/third_party/rust/autocfg-0.1.6/src/version.rs b/third_party/rust/autocfg-0.1.6/src/version.rs
deleted file mode 100644
index 378c21e61e0cdc15253124e63d20503f599b679e..0000000000000000000000000000000000000000
--- a/third_party/rust/autocfg-0.1.6/src/version.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use std::path::Path;
-use std::process::Command;
-use std::str;
-
-use super::{error, Error};
-
-/// A version structure for making relative comparisons.
-#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Version {
-    major: usize,
-    minor: usize,
-    patch: usize,
-}
-
-impl Version {
-    /// Creates a `Version` instance for a specific `major.minor.patch` version.
-    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
-        Version {
-            major: major,
-            minor: minor,
-            patch: patch,
-        }
-    }
-
-    pub fn from_rustc(rustc: &Path) -> Result<Self, Error> {
-        // Get rustc's verbose version
-        let output = try!(Command::new(rustc)
-            .args(&["--version", "--verbose"])
-            .output()
-            .map_err(error::from_io));
-        if !output.status.success() {
-            return Err(error::from_str("could not execute rustc"));
-        }
-        let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
-
-        // Find the release line in the verbose version output.
-        let release = match output.lines().find(|line| line.starts_with("release: ")) {
-            Some(line) => &line["release: ".len()..],
-            None => return Err(error::from_str("could not find rustc release")),
-        };
-
-        // Strip off any extra channel info, e.g. "-beta.N", "-nightly"
-        let version = match release.find('-') {
-            Some(i) => &release[..i],
-            None => release,
-        };
-
-        // Split the version into semver components.
-        let mut iter = version.splitn(3, '.');
-        let major = try!(iter.next().ok_or(error::from_str("missing major version")));
-        let minor = try!(iter.next().ok_or(error::from_str("missing minor version")));
-        let patch = try!(iter.next().ok_or(error::from_str("missing patch version")));
-
-        Ok(Version::new(
-            try!(major.parse().map_err(error::from_num)),
-            try!(minor.parse().map_err(error::from_num)),
-            try!(patch.parse().map_err(error::from_num)),
-        ))
-    }
-}
diff --git a/third_party/rust/crossbeam-channel/.cargo-checksum.json b/third_party/rust/crossbeam-channel/.cargo-checksum.json
index e232bc9cbefe041094f4629b9a55a13a6d033124..11d72285ceff64668d4d3e57c6f35674daa47d1e 100644
--- a/third_party/rust/crossbeam-channel/.cargo-checksum.json
+++ b/third_party/rust/crossbeam-channel/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"0d433ba4c2a327604b582aa0cdbe7b841ee9dcca526f6cb368a07c389c485096","Cargo.lock":"97e544df9b9e169d315994dc220e7a274ac039a3a4f372f7cab333a2e93d9b96","Cargo.toml":"a493466e1330e58126818f0e46b82350ad9e6a7811ca6817159fcdd89c8c871a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"924a49392dc8304def57586be4ebd69aaf51e16fd245b55b4b69ad2cce6b715a","README.md":"d2c041f6fa5da30a6f87377421a8de4010c0c002dbff777e18ad2f8b36a65378","benches/crossbeam.rs":"f5720508d3458f2451271b9887f7557823304bd38288c928b0d6aa1f459865e5","examples/fibonacci.rs":"6a26ecd74c7493d2c93f4280c0804afc19adc612b77b3d9fea433119ff472a44","examples/matching.rs":"63c250e164607a7a9f643d46f107bb5da846d49e89cf9069909562d20e530f71","examples/stopwatch.rs":"87e4613e24083e877d97aaefdc6c78ee0308c3a2994974b2cbc7df042a82d488","src/channel.rs":"de23e68e7fa16a1e3278bd69f22fd499724e21533b2b601a71dada9cdda97181","src/context.rs":"ad24cabfc50dd5e6ae84aa46a0246da12da1f1a6fa19043244ad25136075c6ca","src/counter.rs":"8b6d4d69db59bc992ddc7ed33f709788c3fab482521bb1adf985f77499506c09","src/err.rs":"fdbde7279a1e74973e5c7d3e835a97836229a357fe465c0ba1a37f2a012d1bef","src/flavors/array.rs":"59d43e7292f5e3f7f1bb7799fdf99d97aae763ac93d2c1c2e0e807cbbae1657b","src/flavors/at.rs":"e6a169d91ee1057080b0ef55f3e38471212b4ef225e2cdc2fd25b2262371f921","src/flavors/list.rs":"fa6667a33e30fad94a8432b78dd70d143e0809ebf80fa881bb6221aca55b4229","src/flavors/mod.rs":"6188db53712b10add58364e3031101833d9fb0e384f3a2894c38c8b11abe4cdf","src/flavors/never.rs":"59ac4a46b5e32780b2b2f338064544a8b4ec1bc8b78a8a9cd0a683bcd01d5d36","src/flavors/tick.rs":"667fcaacb07d7556350a7e59b5906956224c57b1f43b7b0018a5e2dad0d91ff8","src/flavors/zero.rs":"97c13c89bce0ffd4f761a5ecd73e3221bdd320817061ef7bc7d76010da021b77","src/lib.rs":"5873568968cfd92c6970ef9c3b2643a9d68c61f2fe4c724e52243f3b555de758","src/select.rs":"da9446e51bdcc51e878e71d7a97f0b718639ea065d7ddf4fa7b561efebc84a0e","src/select_macro.rs":"96bc9acb9a22588a4e733b0ab0761ad2be9a6b3e03744e8fc9c6de9ae433b696","src/utils.rs":"4ec0d30835f42dffc7614a18c8f005abb40dd33f2b127809b297959c6aa43004","src/waker.rs":"27eb84dcd0eb58f7d0d79d412bb293becc2740f6166d2fc64acb0ad94cfb523e","tests/after.rs":"324c7d773f72bef62d150171f74ba7b7ac1b06f6030b3d4d2b1a35d211956b21","tests/array.rs":"62290dfd66740a1d1017daea8048df09a11ee8ff8eb614a3a0aa5f4d456a7c39","tests/golang.rs":"751743529b0354d152916e0854a0387ca0b3a898a1771c46e1e7fa2b1660edf9","tests/iter.rs":"7563dc7fdf4c63e31dd74ee3fedecdd3aed490f7ef599b98f6f75f929cf79edb","tests/list.rs":"6a9645c00aed88c1ad07d2e416b4f137ccef2e50f389c71589c6ac7d57373e5a","tests/mpsc.rs":"0c4c6b056f5cec77ca19eca45f99b083632700a4b67133e88071a1d22a61d6fe","tests/never.rs":"665441a9fb004f7cd44047619637ebe6766cf2faf58e68e6481397bbfc682e11","tests/ready.rs":"3848ee8bb16cc83269a462d830659ff29f91834eaab0749bca7be02f43d7db51","tests/same_channel.rs":"2bab761443671e841e1b2476bd8082d75533a2f6be7946f5dbcee67cdc82dccb","tests/select.rs":"58aa5421475bd98b3adc02e4241fc77669ca910cf9cac7a8b0a212b2e92cb7c7","tests/select_macro.rs":"00dd7963f79b96abf30851fdab29e86c8424b502a8a7d34abf4bc1714f493ecf","tests/thread_locals.rs":"3611db5502e6af0a8d15187d09fd195381819795544208b946e9f99b04579a81","tests/tick.rs":"06f205ace5fc44daaf1b6900a2e05bb5bda1c6071c1a07524f45769d8855968b","tests/zero.rs":"368eac99c6d9fb679f8dfbe93cdb96b01d77d1b6f840aa4e156b06f1786bb882"},"package":"dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"74ac49b84461217698d4430f81b1cdcba0595bc4e57216ffc52b8296ac44cd41","Cargo.lock":"7956079bcac40cc40c894f0260266365ecdb1c01c48636ae4c4080977603e7b8","Cargo.toml":"6a7acaffaa30dab2b5ea1f5ab86b20bc97370314ed03472288745b3b969786dc","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","LICENSE-THIRD-PARTY":"b16db96b93b1d7cf7bea533f572091ec6bca3234fbe0a83038be772ff391a44c","README.md":"415a71d4978cfd338a6ae1f1b41284652eccd277a815542c304647dc437a8274","benches/crossbeam.rs":"f5720508d3458f2451271b9887f7557823304bd38288c928b0d6aa1f459865e5","examples/fibonacci.rs":"6a26ecd74c7493d2c93f4280c0804afc19adc612b77b3d9fea433119ff472a44","examples/matching.rs":"63c250e164607a7a9f643d46f107bb5da846d49e89cf9069909562d20e530f71","examples/stopwatch.rs":"f9a00477b41823199e4af06bddeb0c6cfd22e272340eec1b98b333fc59ee6a1f","src/channel.rs":"a9baaad2f414c38cd324a60ac9375ca58462ce6662217683648e9b66cec43a8c","src/context.rs":"ad24cabfc50dd5e6ae84aa46a0246da12da1f1a6fa19043244ad25136075c6ca","src/counter.rs":"c49a9f44587888850edeb62f7c8ecd1acecb39c836834254ff3ac934c478440a","src/err.rs":"fdbde7279a1e74973e5c7d3e835a97836229a357fe465c0ba1a37f2a012d1bef","src/flavors/array.rs":"c125146771265058ac320226456b1e21667e93649531a3d20157f71cd715881d","src/flavors/at.rs":"65bf870b3ddb14738256706b0276f2656ad1fe9cd8eb91737489868edd088e92","src/flavors/list.rs":"50dbe59616c39b5aa184470023ce0cfb1cb0dbd92e1577375d299446981527c0","src/flavors/mod.rs":"3d9d43bc38b0adb18c96c995c2bd3421d8e33ab6c30b20c3c467d21d48e485dc","src/flavors/never.rs":"0e7921922d00c711552fb063c63c78192fa6ddc0762fb81c1713b847495ec39a","src/flavors/tick.rs":"38a479b9f4a72a5ccb9c407a1e7b44d36b6ad0f4e214e39266b12b9564c803dc","src/flavors/zero.rs":"1bda0c5483b04d53f36f9f4a6fe6f87b69f698068771e637e224c09400c6ce83","src/lib.rs":"3a65706d4124844ffc4c8cb1f8cc779631ec94f449f85cbb68364ad3619404f1","src/select.rs":"4eb4b1988c5dffff3e3d2138d14a1b86613bf62b78c45a5c70f65aaee92c11bb","src/select_macro.rs":"96bc9acb9a22588a4e733b0ab0761ad2be9a6b3e03744e8fc9c6de9ae433b696","src/utils.rs":"746fe315d6cfc832e3dda35e5055c0fd5c99907f1303b2ea7eacc4e37c8527e1","src/waker.rs":"9058cc441d467539c439ef88f0be1a187bf122d26fc116ce3e3a0265a693761f","tests/after.rs":"324c7d773f72bef62d150171f74ba7b7ac1b06f6030b3d4d2b1a35d211956b21","tests/array.rs":"574bff53aff0b0a8c365bf3f9ad77bb64675df9e6e0714be9c16eeeeac22e4d5","tests/golang.rs":"ec03806945fecd381cfce0634e2d776741423589c92e1bd4d8a431ac20f5d2d0","tests/iter.rs":"7563dc7fdf4c63e31dd74ee3fedecdd3aed490f7ef599b98f6f75f929cf79edb","tests/list.rs":"cc2971e69fd7f6a94b5463c9d4e9079df7955b37552e16dd66f4c6e65db60d96","tests/mpsc.rs":"0c4c6b056f5cec77ca19eca45f99b083632700a4b67133e88071a1d22a61d6fe","tests/never.rs":"665441a9fb004f7cd44047619637ebe6766cf2faf58e68e6481397bbfc682e11","tests/ready.rs":"eae3d7f16e817e63f3a6ceda062fece3de5e11c7a9631b32b02f23396a9d59c1","tests/same_channel.rs":"2bab761443671e841e1b2476bd8082d75533a2f6be7946f5dbcee67cdc82dccb","tests/select.rs":"3603f450b23f5e0d1e4014a167a9b23ab149b5f418c8b89636f1c02c90501569","tests/select_macro.rs":"00dd7963f79b96abf30851fdab29e86c8424b502a8a7d34abf4bc1714f493ecf","tests/thread_locals.rs":"3611db5502e6af0a8d15187d09fd195381819795544208b946e9f99b04579a81","tests/tick.rs":"dc4a7d3c8dd888ce135fe8a8c67f5dc8b5ab0c3fa57a48459f96d51fa0f1e6d5","tests/zero.rs":"0ff0587cc74569bfe389e0c619217799a960a0dfc5e6354603c88e6eea1b79a1"},"package":"06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-channel/CHANGELOG.md b/third_party/rust/crossbeam-channel/CHANGELOG.md
index 0a53e8a0b80a9c220993d216c6fb2b468b6ec7be..98fd9f66daaa271ad9bf9d099e10f3131bcc0fa7 100644
--- a/third_party/rust/crossbeam-channel/CHANGELOG.md
+++ b/third_party/rust/crossbeam-channel/CHANGELOG.md
@@ -1,3 +1,7 @@
+# Version 0.5.1
+
+- Fix memory leak in unbounded channel. (#669)
+
 # Version 0.5.0
 
 - Bump the minimum supported Rust version to 1.36.
diff --git a/third_party/rust/crossbeam-channel/Cargo.lock b/third_party/rust/crossbeam-channel/Cargo.lock
index 91cb58a0f776be0c6b132897695b1d7c0ebe08be..1ae0d57c27dd6a2f35f13adb2e2c298f7d5a3750 100644
--- a/third_party/rust/crossbeam-channel/Cargo.lock
+++ b/third_party/rust/crossbeam-channel/Cargo.lock
@@ -1,10 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-[[package]]
-name = "arc-swap"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
+version = 3
 
 [[package]]
 name = "autocfg"
@@ -12,29 +8,17 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
 
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
-[[package]]
-name = "const_fn"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2"
-
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
  "crossbeam-utils",
  "num_cpus",
  "rand",
@@ -43,32 +27,31 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.0"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5"
+checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
 dependencies = [
  "autocfg",
- "cfg-if 1.0.0",
- "const_fn",
+ "cfg-if",
  "lazy_static",
 ]
 
 [[package]]
 name = "getrandom"
-version = "0.1.15"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
 dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if",
  "libc",
  "wasi",
 ]
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.17"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
 dependencies = [
  "libc",
 ]
@@ -81,9 +64,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.79"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
+checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
 
 [[package]]
 name = "num_cpus"
@@ -97,17 +80,16 @@ dependencies = [
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.9"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
 
 [[package]]
 name = "rand"
-version = "0.7.3"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
 dependencies = [
- "getrandom",
  "libc",
  "rand_chacha",
  "rand_core",
@@ -116,9 +98,9 @@ dependencies = [
 
 [[package]]
 name = "rand_chacha"
-version = "0.2.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
 dependencies = [
  "ppv-lite86",
  "rand_core",
@@ -126,27 +108,27 @@ dependencies = [
 
 [[package]]
 name = "rand_core"
-version = "0.5.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
 dependencies = [
  "getrandom",
 ]
 
 [[package]]
 name = "rand_hc"
-version = "0.2.0"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
 dependencies = [
  "rand_core",
 ]
 
 [[package]]
 name = "signal-hook"
-version = "0.1.16"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "604508c1418b99dfe1925ca9224829bb2a8a9a04dda655cc01fcad46f4ab05ed"
+checksum = "ef33d6d0cd06e0840fba9985aab098c147e67e05cee14d412d3345ed14ff30ac"
 dependencies = [
  "libc",
  "signal-hook-registry",
@@ -154,16 +136,15 @@ dependencies = [
 
 [[package]]
 name = "signal-hook-registry"
-version = "1.2.1"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
+checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
 dependencies = [
- "arc-swap",
  "libc",
 ]
 
 [[package]]
 name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
+version = "0.10.2+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
diff --git a/third_party/rust/crossbeam-channel/Cargo.toml b/third_party/rust/crossbeam-channel/Cargo.toml
index a5c9964af3663ce4c4a82137d7d7a885fcd5e508..abcc485aec3175ee4e30339a349352deb7bf86ff 100644
--- a/third_party/rust/crossbeam-channel/Cargo.toml
+++ b/third_party/rust/crossbeam-channel/Cargo.toml
@@ -13,12 +13,11 @@
 [package]
 edition = "2018"
 name = "crossbeam-channel"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["The Crossbeam Project Developers"]
 description = "Multi-producer multi-consumer channels for message passing"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel"
 documentation = "https://docs.rs/crossbeam-channel"
-readme = "README.md"
 keywords = ["channel", "mpmc", "select", "golang", "message"]
 categories = ["algorithms", "concurrency", "data-structures"]
 license = "MIT OR Apache-2.0"
@@ -34,10 +33,10 @@ default-features = false
 version = "1.13.0"
 
 [dev-dependencies.rand]
-version = "0.7.3"
+version = "0.8"
 
 [dev-dependencies.signal-hook]
-version = "0.1.15"
+version = "0.3"
 
 [features]
 default = ["std"]
diff --git a/third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY b/third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY
index d15e32bc714aecfe86b88330c0ed1ab0a4739cd5..ed4df76f4cef9d233f168ef033908ab0809be143 100644
--- a/third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY
+++ b/third_party/rust/crossbeam-channel/LICENSE-THIRD-PARTY
@@ -1,37 +1,5 @@
 ===============================================================================
 
-Bounded MPMC queue
-http://www.1024cores.net/home/code-license
-
-Copyright (c) 2010-2011 Dmitry Vyukov.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-The views and conclusions contained in the software and documentation are those
-of the authors and should not be interpreted as representing official policies,
-either expressed or implied, of Dmitry Vyukov.
-
-===============================================================================
-
 matching.go
 https://creativecommons.org/licenses/by/3.0/legalcode
 
diff --git a/third_party/rust/crossbeam-channel/README.md b/third_party/rust/crossbeam-channel/README.md
index eab623a6a9ab22c9a8116208388cf4f0d0b7835e..f5077c556c831b7ac773877f4ab284b874da3a45 100644
--- a/third_party/rust/crossbeam-channel/README.md
+++ b/third_party/rust/crossbeam-channel/README.md
@@ -2,7 +2,7 @@
 
 [![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)](
 https://github.com/crossbeam-rs/crossbeam/actions)
-[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](
+[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)](
 https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel#license)
 [![Cargo](https://img.shields.io/crates/v/crossbeam-channel.svg)](
 https://crates.io/crates/crossbeam-channel)
@@ -10,7 +10,7 @@ https://crates.io/crates/crossbeam-channel)
 https://docs.rs/crossbeam-channel)
 [![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)](
 https://www.rust-lang.org)
-[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq)
+[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ)
 
 This crate provides multi-producer multi-consumer channels for message passing.
 It is an alternative to [`std::sync::mpsc`] with more features and better performance.
@@ -41,7 +41,7 @@ Add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-crossbeam-channel = "0.4"
+crossbeam-channel = "0.5"
 ```
 
 ## Compatibility
@@ -73,10 +73,6 @@ This product includes copies and modifications of software developed by third pa
   [matching.go](http://www.nada.kth.se/~snilsson/concurrency/src/matching.go) by Stefan Nilsson,
   licensed under Creative Commons Attribution 3.0 Unported License.
 
-* [src/flavors/array.rs](src/flavors/array.rs) is based on
-  [Bounded MPMC queue](http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue)
-  by Dmitry Vyukov, licensed under the Simplified BSD License and the Apache License, Version 2.0.
-
 * [tests/mpsc.rs](tests/mpsc.rs) includes modifications of code from The Rust Programming Language,
   licensed under the MIT License and the Apache License, Version 2.0.
 
diff --git a/third_party/rust/crossbeam-channel/examples/stopwatch.rs b/third_party/rust/crossbeam-channel/examples/stopwatch.rs
index 6a67c9eefc46db83dd822fc6a1c5f7e3b46d47a2..98895c5a3a466073fa73b9c68a537b1933732785 100644
--- a/third_party/rust/crossbeam-channel/examples/stopwatch.rs
+++ b/third_party/rust/crossbeam-channel/examples/stopwatch.rs
@@ -12,13 +12,13 @@ fn main() {
     use std::time::{Duration, Instant};
 
     use crossbeam_channel::{bounded, select, tick, Receiver};
+    use signal_hook::consts::SIGINT;
     use signal_hook::iterator::Signals;
-    use signal_hook::SIGINT;
 
     // Creates a channel that gets a message every time `SIGINT` is signalled.
     fn sigint_notifier() -> io::Result<Receiver<()>> {
         let (s, r) = bounded(100);
-        let signals = Signals::new(&[SIGINT])?;
+        let mut signals = Signals::new(&[SIGINT])?;
 
         thread::spawn(move || {
             for _ in signals.forever() {
diff --git a/third_party/rust/crossbeam-channel/src/channel.rs b/third_party/rust/crossbeam-channel/src/channel.rs
index ebcd6520189bc8b13ba26724f10279984ae8e2fe..8988235db45e240cf7650d280c475cbb435dac4f 100644
--- a/third_party/rust/crossbeam-channel/src/channel.rs
+++ b/third_party/rust/crossbeam-channel/src/channel.rs
@@ -257,8 +257,6 @@ pub fn at(when: Instant) -> Receiver<Instant> {
 ///     recv(timeout) -> _ => println!("timed out"),
 /// }
 /// ```
-///
-/// [`select!`]: macro.select.html
 pub fn never<T>() -> Receiver<T> {
     Receiver {
         flavor: ReceiverFlavor::Never(flavors::never::Channel::new()),
@@ -645,7 +643,7 @@ impl<T> Drop for Sender<T> {
         unsafe {
             match &self.flavor {
                 SenderFlavor::Array(chan) => chan.release(|c| c.disconnect()),
-                SenderFlavor::List(chan) => chan.release(|c| c.disconnect()),
+                SenderFlavor::List(chan) => chan.release(|c| c.disconnect_senders()),
                 SenderFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
             }
         }
@@ -1137,7 +1135,7 @@ impl<T> Drop for Receiver<T> {
         unsafe {
             match &self.flavor {
                 ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect()),
-                ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect()),
+                ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect_receivers()),
                 ReceiverFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
                 ReceiverFlavor::At(_) => {}
                 ReceiverFlavor::Tick(_) => {}
@@ -1485,7 +1483,7 @@ impl<T> SelectHandle for Receiver<T> {
 }
 
 /// Writes a message into the channel.
-pub unsafe fn write<T>(s: &Sender<T>, token: &mut Token, msg: T) -> Result<(), T> {
+pub(crate) unsafe fn write<T>(s: &Sender<T>, token: &mut Token, msg: T) -> Result<(), T> {
     match &s.flavor {
         SenderFlavor::Array(chan) => chan.write(token, msg),
         SenderFlavor::List(chan) => chan.write(token, msg),
@@ -1494,7 +1492,7 @@ pub unsafe fn write<T>(s: &Sender<T>, token: &mut Token, msg: T) -> Result<(), T
 }
 
 /// Reads a message from the channel.
-pub unsafe fn read<T>(r: &Receiver<T>, token: &mut Token) -> Result<T, ()> {
+pub(crate) unsafe fn read<T>(r: &Receiver<T>, token: &mut Token) -> Result<T, ()> {
     match &r.flavor {
         ReceiverFlavor::Array(chan) => chan.read(token),
         ReceiverFlavor::List(chan) => chan.read(token),
diff --git a/third_party/rust/crossbeam-channel/src/counter.rs b/third_party/rust/crossbeam-channel/src/counter.rs
index 2eaf06782042465fde984a0215c280f6b8a26cd9..2c27f7c6b2e1a2b807e3f468c12e365325d450c6 100644
--- a/third_party/rust/crossbeam-channel/src/counter.rs
+++ b/third_party/rust/crossbeam-channel/src/counter.rs
@@ -21,7 +21,7 @@ struct Counter<C> {
 }
 
 /// Wraps a channel into the reference counter.
-pub fn new<C>(chan: C) -> (Sender<C>, Receiver<C>) {
+pub(crate) fn new<C>(chan: C) -> (Sender<C>, Receiver<C>) {
     let counter = Box::into_raw(Box::new(Counter {
         senders: AtomicUsize::new(1),
         receivers: AtomicUsize::new(1),
@@ -34,7 +34,7 @@ pub fn new<C>(chan: C) -> (Sender<C>, Receiver<C>) {
 }
 
 /// The sending side.
-pub struct Sender<C> {
+pub(crate) struct Sender<C> {
     counter: *mut Counter<C>,
 }
 
@@ -45,7 +45,7 @@ impl<C> Sender<C> {
     }
 
     /// Acquires another sender reference.
-    pub fn acquire(&self) -> Sender<C> {
+    pub(crate) fn acquire(&self) -> Sender<C> {
         let count = self.counter().senders.fetch_add(1, Ordering::Relaxed);
 
         // Cloning senders and calling `mem::forget` on the clones could potentially overflow the
@@ -63,7 +63,7 @@ impl<C> Sender<C> {
     /// Releases the sender reference.
     ///
     /// Function `disconnect` will be called if this is the last sender reference.
-    pub unsafe fn release<F: FnOnce(&C) -> bool>(&self, disconnect: F) {
+    pub(crate) unsafe fn release<F: FnOnce(&C) -> bool>(&self, disconnect: F) {
         if self.counter().senders.fetch_sub(1, Ordering::AcqRel) == 1 {
             disconnect(&self.counter().chan);
 
@@ -89,7 +89,7 @@ impl<C> PartialEq for Sender<C> {
 }
 
 /// The receiving side.
-pub struct Receiver<C> {
+pub(crate) struct Receiver<C> {
     counter: *mut Counter<C>,
 }
 
@@ -100,7 +100,7 @@ impl<C> Receiver<C> {
     }
 
     /// Acquires another receiver reference.
-    pub fn acquire(&self) -> Receiver<C> {
+    pub(crate) fn acquire(&self) -> Receiver<C> {
         let count = self.counter().receivers.fetch_add(1, Ordering::Relaxed);
 
         // Cloning receivers and calling `mem::forget` on the clones could potentially overflow the
@@ -118,7 +118,7 @@ impl<C> Receiver<C> {
     /// Releases the receiver reference.
     ///
     /// Function `disconnect` will be called if this is the last receiver reference.
-    pub unsafe fn release<F: FnOnce(&C) -> bool>(&self, disconnect: F) {
+    pub(crate) unsafe fn release<F: FnOnce(&C) -> bool>(&self, disconnect: F) {
         if self.counter().receivers.fetch_sub(1, Ordering::AcqRel) == 1 {
             disconnect(&self.counter().chan);
 
diff --git a/third_party/rust/crossbeam-channel/src/flavors/array.rs b/third_party/rust/crossbeam-channel/src/flavors/array.rs
index 323a200c25dc5082c97d11c5148d4716aa18e5bb..c49eef1f04310a5d5b43739118f5a63db22e8d4d 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/array.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/array.rs
@@ -5,13 +5,8 @@
 //! The implementation is based on Dmitry Vyukov's bounded MPMC queue.
 //!
 //! Source:
-//!   - http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
-//!   - https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub
-//!
-//! Copyright & License:
-//!   - Copyright (c) 2010-2011 Dmitry Vyukov
-//!   - Simplified BSD License and Apache License, Version 2.0
-//!   - http://www.1024cores.net/home/code-license
+//!   - <http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue>
+//!   - <https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub>
 
 use std::cell::UnsafeCell;
 use std::marker::PhantomData;
@@ -57,7 +52,7 @@ impl Default for ArrayToken {
 }
 
 /// Bounded channel based on a preallocated array.
-pub struct Channel<T> {
+pub(crate) struct Channel<T> {
     /// The head of the channel.
     ///
     /// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but
@@ -100,7 +95,7 @@ pub struct Channel<T> {
 
 impl<T> Channel<T> {
     /// Creates a bounded channel of capacity `cap`.
-    pub fn with_capacity(cap: usize) -> Self {
+    pub(crate) fn with_capacity(cap: usize) -> Self {
         assert!(cap > 0, "capacity must be positive");
 
         // Compute constants `mark_bit` and `one_lap`.
@@ -143,12 +138,12 @@ impl<T> Channel<T> {
     }
 
     /// Returns a receiver handle to the channel.
-    pub fn receiver(&self) -> Receiver<'_, T> {
+    pub(crate) fn receiver(&self) -> Receiver<'_, T> {
         Receiver(self)
     }
 
     /// Returns a sender handle to the channel.
-    pub fn sender(&self) -> Sender<'_, T> {
+    pub(crate) fn sender(&self) -> Sender<'_, T> {
         Sender(self)
     }
 
@@ -224,7 +219,7 @@ impl<T> Channel<T> {
     }
 
     /// Writes a message into the channel.
-    pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
+    pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
         // If there is no slot, the channel is disconnected.
         if token.array.slot.is_null() {
             return Err(msg);
@@ -314,7 +309,7 @@ impl<T> Channel<T> {
     }
 
     /// Reads a message from the channel.
-    pub unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
+    pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
         if token.array.slot.is_null() {
             // The channel is disconnected.
             return Err(());
@@ -332,7 +327,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to send a message into the channel.
-    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
+    pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
         let token = &mut Token::default();
         if self.start_send(token) {
             unsafe { self.write(token, msg).map_err(TrySendError::Disconnected) }
@@ -342,7 +337,11 @@ impl<T> Channel<T> {
     }
 
     /// Sends a message into the channel.
-    pub fn send(&self, msg: T, deadline: Option<Instant>) -> Result<(), SendTimeoutError<T>> {
+    pub(crate) fn send(
+        &self,
+        msg: T,
+        deadline: Option<Instant>,
+    ) -> Result<(), SendTimeoutError<T>> {
         let token = &mut Token::default();
         loop {
             // Try sending a message several times.
@@ -391,7 +390,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to receive a message without blocking.
-    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
         let token = &mut Token::default();
 
         if self.start_recv(token) {
@@ -402,7 +401,7 @@ impl<T> Channel<T> {
     }
 
     /// Receives a message from the channel.
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
         let token = &mut Token::default();
         loop {
             // Try receiving a message several times.
@@ -453,7 +452,7 @@ impl<T> Channel<T> {
     }
 
     /// Returns the current number of messages inside the channel.
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         loop {
             // Load the tail, then load the head.
             let tail = self.tail.load(Ordering::SeqCst);
@@ -478,14 +477,15 @@ impl<T> Channel<T> {
     }
 
     /// Returns the capacity of the channel.
-    pub fn capacity(&self) -> Option<usize> {
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
+    pub(crate) fn capacity(&self) -> Option<usize> {
         Some(self.cap)
     }
 
     /// Disconnects the channel and wakes up all blocked senders and receivers.
     ///
     /// Returns `true` if this call disconnected the channel.
-    pub fn disconnect(&self) -> bool {
+    pub(crate) fn disconnect(&self) -> bool {
         let tail = self.tail.fetch_or(self.mark_bit, Ordering::SeqCst);
 
         if tail & self.mark_bit == 0 {
@@ -498,12 +498,12 @@ impl<T> Channel<T> {
     }
 
     /// Returns `true` if the channel is disconnected.
-    pub fn is_disconnected(&self) -> bool {
+    pub(crate) fn is_disconnected(&self) -> bool {
         self.tail.load(Ordering::SeqCst) & self.mark_bit != 0
     }
 
     /// Returns `true` if the channel is empty.
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         let head = self.head.load(Ordering::SeqCst);
         let tail = self.tail.load(Ordering::SeqCst);
 
@@ -515,7 +515,7 @@ impl<T> Channel<T> {
     }
 
     /// Returns `true` if the channel is full.
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         let tail = self.tail.load(Ordering::SeqCst);
         let head = self.head.load(Ordering::SeqCst);
 
@@ -563,10 +563,10 @@ impl<T> Drop for Channel<T> {
 }
 
 /// Receiver handle to a channel.
-pub struct Receiver<'a, T>(&'a Channel<T>);
+pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
 
 /// Sender handle to a channel.
-pub struct Sender<'a, T>(&'a Channel<T>);
+pub(crate) struct Sender<'a, T>(&'a Channel<T>);
 
 impl<T> SelectHandle for Receiver<'_, T> {
     fn try_select(&self, token: &mut Token) -> bool {
diff --git a/third_party/rust/crossbeam-channel/src/flavors/at.rs b/third_party/rust/crossbeam-channel/src/flavors/at.rs
index a2b1b578ec228f46131fdce2714063ff3d4c182a..4581edba1247a9675bd7dbc0e00f88f3ac4b2aa8 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/at.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/at.rs
@@ -12,10 +12,10 @@ use crate::select::{Operation, SelectHandle, Token};
 use crate::utils;
 
 /// Result of a receive operation.
-pub type AtToken = Option<Instant>;
+pub(crate) type AtToken = Option<Instant>;
 
 /// Channel that delivers a message at a certain moment in time
-pub struct Channel {
+pub(crate) struct Channel {
     /// The instant at which the message will be delivered.
     delivery_time: Instant,
 
@@ -26,7 +26,7 @@ pub struct Channel {
 impl Channel {
     /// Creates a channel that delivers a message at a certain instant in time.
     #[inline]
-    pub fn new_deadline(when: Instant) -> Self {
+    pub(crate) fn new_deadline(when: Instant) -> Self {
         Channel {
             delivery_time: when,
             received: AtomicBool::new(false),
@@ -34,13 +34,13 @@ impl Channel {
     }
     /// Creates a channel that delivers a message after a certain duration of time.
     #[inline]
-    pub fn new_timeout(dur: Duration) -> Self {
+    pub(crate) fn new_timeout(dur: Duration) -> Self {
         Self::new_deadline(Instant::now() + dur)
     }
 
     /// Attempts to receive a message without blocking.
     #[inline]
-    pub fn try_recv(&self) -> Result<Instant, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<Instant, TryRecvError> {
         // We use relaxed ordering because this is just an optional optimistic check.
         if self.received.load(Ordering::Relaxed) {
             // The message has already been received.
@@ -64,7 +64,7 @@ impl Channel {
 
     /// Receives a message from the channel.
     #[inline]
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> {
         // We use relaxed ordering because this is just an optional optimistic check.
         if self.received.load(Ordering::Relaxed) {
             // The message has already been received.
@@ -103,13 +103,13 @@ impl Channel {
 
     /// Reads a message from the channel.
     #[inline]
-    pub unsafe fn read(&self, token: &mut Token) -> Result<Instant, ()> {
+    pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<Instant, ()> {
         token.at.ok_or(())
     }
 
     /// Returns `true` if the channel is empty.
     #[inline]
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         // We use relaxed ordering because this is just an optional optimistic check.
         if self.received.load(Ordering::Relaxed) {
             return true;
@@ -127,13 +127,13 @@ impl Channel {
 
     /// Returns `true` if the channel is full.
     #[inline]
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         !self.is_empty()
     }
 
     /// Returns the number of messages in the channel.
     #[inline]
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         if self.is_empty() {
             0
         } else {
@@ -142,8 +142,9 @@ impl Channel {
     }
 
     /// Returns the capacity of the channel.
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
-    pub fn capacity(&self) -> Option<usize> {
+    pub(crate) fn capacity(&self) -> Option<usize> {
         Some(1)
     }
 }
diff --git a/third_party/rust/crossbeam-channel/src/flavors/list.rs b/third_party/rust/crossbeam-channel/src/flavors/list.rs
index 532e8b6ad41c4e38862d2e5aabf9d0b7995b14d3..5056aa431326ae02eadc235e2a2f9aae48d6d353 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/list.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/list.rs
@@ -151,7 +151,7 @@ impl Default for ListToken {
 ///
 /// Consecutive messages are grouped into blocks in order to put less pressure on the allocator and
 /// improve cache efficiency.
-pub struct Channel<T> {
+pub(crate) struct Channel<T> {
     /// The head of the channel.
     head: CachePadded<Position<T>>,
 
@@ -167,7 +167,7 @@ pub struct Channel<T> {
 
 impl<T> Channel<T> {
     /// Creates a new unbounded channel.
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Channel {
             head: CachePadded::new(Position {
                 block: AtomicPtr::new(ptr::null_mut()),
@@ -183,12 +183,12 @@ impl<T> Channel<T> {
     }
 
     /// Returns a receiver handle to the channel.
-    pub fn receiver(&self) -> Receiver<'_, T> {
+    pub(crate) fn receiver(&self) -> Receiver<'_, T> {
         Receiver(self)
     }
 
     /// Returns a sender handle to the channel.
-    pub fn sender(&self) -> Sender<'_, T> {
+    pub(crate) fn sender(&self) -> Sender<'_, T> {
         Sender(self)
     }
 
@@ -231,8 +231,8 @@ impl<T> Channel<T> {
                 if self
                     .tail
                     .block
-                    .compare_and_swap(block, new, Ordering::Release)
-                    == block
+                    .compare_exchange(block, new, Ordering::Release, Ordering::Relaxed)
+                    .is_ok()
                 {
                     self.head.block.store(new, Ordering::Release);
                     block = new;
@@ -276,7 +276,7 @@ impl<T> Channel<T> {
     }
 
     /// Writes a message into the channel.
-    pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
+    pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
         // If there is no slot, the channel is disconnected.
         if token.list.block.is_null() {
             return Err(msg);
@@ -380,7 +380,7 @@ impl<T> Channel<T> {
     }
 
     /// Reads a message from the channel.
-    pub unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
+    pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
         if token.list.block.is_null() {
             // The channel is disconnected.
             return Err(());
@@ -405,7 +405,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to send a message into the channel.
-    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
+    pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
         self.send(msg, None).map_err(|err| match err {
             SendTimeoutError::Disconnected(msg) => TrySendError::Disconnected(msg),
             SendTimeoutError::Timeout(_) => unreachable!(),
@@ -413,7 +413,11 @@ impl<T> Channel<T> {
     }
 
     /// Sends a message into the channel.
-    pub fn send(&self, msg: T, _deadline: Option<Instant>) -> Result<(), SendTimeoutError<T>> {
+    pub(crate) fn send(
+        &self,
+        msg: T,
+        _deadline: Option<Instant>,
+    ) -> Result<(), SendTimeoutError<T>> {
         let token = &mut Token::default();
         assert!(self.start_send(token));
         unsafe {
@@ -423,7 +427,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to receive a message without blocking.
-    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
         let token = &mut Token::default();
 
         if self.start_recv(token) {
@@ -434,7 +438,7 @@ impl<T> Channel<T> {
     }
 
     /// Receives a message from the channel.
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
         let token = &mut Token::default();
         loop {
             // Try receiving a message several times.
@@ -486,7 +490,7 @@ impl<T> Channel<T> {
     }
 
     /// Returns the current number of messages inside the channel.
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         loop {
             // Load the tail index, then load the head index.
             let mut tail = self.tail.index.load(Ordering::SeqCst);
@@ -522,14 +526,14 @@ impl<T> Channel<T> {
     }
 
     /// Returns the capacity of the channel.
-    pub fn capacity(&self) -> Option<usize> {
+    pub(crate) fn capacity(&self) -> Option<usize> {
         None
     }
 
-    /// Disconnects the channel and wakes up all blocked receivers.
+    /// Disconnects senders and wakes up all blocked receivers.
     ///
     /// Returns `true` if this call disconnected the channel.
-    pub fn disconnect(&self) -> bool {
+    pub(crate) fn disconnect_senders(&self) -> bool {
         let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst);
 
         if tail & MARK_BIT == 0 {
@@ -540,20 +544,90 @@ impl<T> Channel<T> {
         }
     }
 
+    /// Disconnects receivers.
+    ///
+    /// Returns `true` if this call disconnected the channel.
+    pub(crate) fn disconnect_receivers(&self) -> bool {
+        let tail = self.tail.index.fetch_or(MARK_BIT, Ordering::SeqCst);
+
+        if tail & MARK_BIT == 0 {
+            // If receivers are dropped first, discard all messages to free
+            // memory eagerly.
+            self.discard_all_messages();
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Discards all messages.
+    ///
+    /// This method should only be called when all receivers are dropped.
+    fn discard_all_messages(&self) {
+        let backoff = Backoff::new();
+        let mut tail = self.tail.index.load(Ordering::Acquire);
+        loop {
+            let offset = (tail >> SHIFT) % LAP;
+            if offset != BLOCK_CAP {
+                break;
+            }
+
+            // New updates to tail will be rejected by MARK_BIT and aborted unless it's
+            // at boundary. We need to wait for the updates take affect otherwise there
+            // can be memory leaks.
+            backoff.snooze();
+            tail = self.tail.index.load(Ordering::Acquire);
+        }
+
+        let mut head = self.head.index.load(Ordering::Acquire);
+        let mut block = self.head.block.load(Ordering::Acquire);
+
+        unsafe {
+            // Drop all messages between head and tail and deallocate the heap-allocated blocks.
+            while head >> SHIFT != tail >> SHIFT {
+                let offset = (head >> SHIFT) % LAP;
+
+                if offset < BLOCK_CAP {
+                    // Drop the message in the slot.
+                    let slot = (*block).slots.get_unchecked(offset);
+                    slot.wait_write();
+                    let p = &mut *slot.msg.get();
+                    p.as_mut_ptr().drop_in_place();
+                } else {
+                    (*block).wait_next();
+                    // Deallocate the block and move to the next one.
+                    let next = (*block).next.load(Ordering::Acquire);
+                    drop(Box::from_raw(block));
+                    block = next;
+                }
+
+                head = head.wrapping_add(1 << SHIFT);
+            }
+
+            // Deallocate the last remaining block.
+            if !block.is_null() {
+                drop(Box::from_raw(block));
+            }
+        }
+        head &= !MARK_BIT;
+        self.head.block.store(ptr::null_mut(), Ordering::Release);
+        self.head.index.store(head, Ordering::Release);
+    }
+
     /// Returns `true` if the channel is disconnected.
-    pub fn is_disconnected(&self) -> bool {
+    pub(crate) fn is_disconnected(&self) -> bool {
         self.tail.index.load(Ordering::SeqCst) & MARK_BIT != 0
     }
 
     /// Returns `true` if the channel is empty.
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         let head = self.head.index.load(Ordering::SeqCst);
         let tail = self.tail.index.load(Ordering::SeqCst);
         head >> SHIFT == tail >> SHIFT
     }
 
     /// Returns `true` if the channel is full.
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         false
     }
 }
@@ -597,10 +671,10 @@ impl<T> Drop for Channel<T> {
 }
 
 /// Receiver handle to a channel.
-pub struct Receiver<'a, T>(&'a Channel<T>);
+pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
 
 /// Sender handle to a channel.
-pub struct Sender<'a, T>(&'a Channel<T>);
+pub(crate) struct Sender<'a, T>(&'a Channel<T>);
 
 impl<T> SelectHandle for Receiver<'_, T> {
     fn try_select(&self, token: &mut Token) -> bool {
diff --git a/third_party/rust/crossbeam-channel/src/flavors/mod.rs b/third_party/rust/crossbeam-channel/src/flavors/mod.rs
index 299e78f69687a8b508ed699157dbeb5b96e6859f..0314bf42097e8643c2b59d2c8efad593a9f008d2 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/mod.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/mod.rs
@@ -9,9 +9,9 @@
 //! 5. `tick` - Channel that delivers messages periodically.
 //! 6. `zero` - Zero-capacity channel.
 
-pub mod array;
-pub mod at;
-pub mod list;
-pub mod never;
-pub mod tick;
-pub mod zero;
+pub(crate) mod array;
+pub(crate) mod at;
+pub(crate) mod list;
+pub(crate) mod never;
+pub(crate) mod tick;
+pub(crate) mod zero;
diff --git a/third_party/rust/crossbeam-channel/src/flavors/never.rs b/third_party/rust/crossbeam-channel/src/flavors/never.rs
index e49d2147c44b75d97adc64cd8cfce085db159e75..1951e963faf8af1525f1896d546b7b37939f2cd1 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/never.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/never.rs
@@ -11,17 +11,17 @@ use crate::select::{Operation, SelectHandle, Token};
 use crate::utils;
 
 /// This flavor doesn't need a token.
-pub type NeverToken = ();
+pub(crate) type NeverToken = ();
 
 /// Channel that never delivers messages.
-pub struct Channel<T> {
+pub(crate) struct Channel<T> {
     _marker: PhantomData<T>,
 }
 
 impl<T> Channel<T> {
     /// Creates a channel that never delivers messages.
     #[inline]
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Channel {
             _marker: PhantomData,
         }
@@ -29,44 +29,45 @@ impl<T> Channel<T> {
 
     /// Attempts to receive a message without blocking.
     #[inline]
-    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
         Err(TryRecvError::Empty)
     }
 
     /// Receives a message from the channel.
     #[inline]
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
         utils::sleep_until(deadline);
         Err(RecvTimeoutError::Timeout)
     }
 
     /// Reads a message from the channel.
     #[inline]
-    pub unsafe fn read(&self, _token: &mut Token) -> Result<T, ()> {
+    pub(crate) unsafe fn read(&self, _token: &mut Token) -> Result<T, ()> {
         Err(())
     }
 
     /// Returns `true` if the channel is empty.
     #[inline]
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         true
     }
 
     /// Returns `true` if the channel is full.
     #[inline]
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         true
     }
 
     /// Returns the number of messages in the channel.
     #[inline]
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         0
     }
 
     /// Returns the capacity of the channel.
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
-    pub fn capacity(&self) -> Option<usize> {
+    pub(crate) fn capacity(&self) -> Option<usize> {
         Some(0)
     }
 }
diff --git a/third_party/rust/crossbeam-channel/src/flavors/tick.rs b/third_party/rust/crossbeam-channel/src/flavors/tick.rs
index e8e7020ca8e2e2368fca8a8b39e3cb203b136385..d4b1f6c78d49fa37d30260e4f807313c8d28a9f4 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/tick.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/tick.rs
@@ -12,10 +12,10 @@ use crate::err::{RecvTimeoutError, TryRecvError};
 use crate::select::{Operation, SelectHandle, Token};
 
 /// Result of a receive operation.
-pub type TickToken = Option<Instant>;
+pub(crate) type TickToken = Option<Instant>;
 
 /// Channel that delivers messages periodically.
-pub struct Channel {
+pub(crate) struct Channel {
     /// The instant at which the next message will be delivered.
     delivery_time: AtomicCell<Instant>,
 
@@ -26,7 +26,7 @@ pub struct Channel {
 impl Channel {
     /// Creates a channel that delivers messages periodically.
     #[inline]
-    pub fn new(dur: Duration) -> Self {
+    pub(crate) fn new(dur: Duration) -> Self {
         Channel {
             delivery_time: AtomicCell::new(Instant::now() + dur),
             duration: dur,
@@ -35,7 +35,7 @@ impl Channel {
 
     /// Attempts to receive a message without blocking.
     #[inline]
-    pub fn try_recv(&self) -> Result<Instant, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<Instant, TryRecvError> {
         loop {
             let now = Instant::now();
             let delivery_time = self.delivery_time.load();
@@ -56,7 +56,7 @@ impl Channel {
 
     /// Receives a message from the channel.
     #[inline]
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<Instant, RecvTimeoutError> {
         loop {
             let delivery_time = self.delivery_time.load();
             let now = Instant::now();
@@ -85,25 +85,25 @@ impl Channel {
 
     /// Reads a message from the channel.
     #[inline]
-    pub unsafe fn read(&self, token: &mut Token) -> Result<Instant, ()> {
+    pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<Instant, ()> {
         token.tick.ok_or(())
     }
 
     /// Returns `true` if the channel is empty.
     #[inline]
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         Instant::now() < self.delivery_time.load()
     }
 
     /// Returns `true` if the channel is full.
     #[inline]
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         !self.is_empty()
     }
 
     /// Returns the number of messages in the channel.
     #[inline]
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         if self.is_empty() {
             0
         } else {
@@ -112,8 +112,9 @@ impl Channel {
     }
 
     /// Returns the capacity of the channel.
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
-    pub fn capacity(&self) -> Option<usize> {
+    pub(crate) fn capacity(&self) -> Option<usize> {
         Some(1)
     }
 }
diff --git a/third_party/rust/crossbeam-channel/src/flavors/zero.rs b/third_party/rust/crossbeam-channel/src/flavors/zero.rs
index be647b55c82f2282321fcde38f002643954d6417..9790b77c230342045eb536a9fc09f6eae54de142 100644
--- a/third_party/rust/crossbeam-channel/src/flavors/zero.rs
+++ b/third_party/rust/crossbeam-channel/src/flavors/zero.rs
@@ -16,7 +16,7 @@ use crate::utils::Spinlock;
 use crate::waker::Waker;
 
 /// A pointer to a packet.
-pub type ZeroToken = usize;
+pub(crate) type ZeroToken = usize;
 
 /// A slot for passing one message from a sender to a receiver.
 struct Packet<T> {
@@ -80,7 +80,7 @@ struct Inner {
 }
 
 /// Zero-capacity channel.
-pub struct Channel<T> {
+pub(crate) struct Channel<T> {
     /// Inner representation of the channel.
     inner: Spinlock<Inner>,
 
@@ -90,7 +90,7 @@ pub struct Channel<T> {
 
 impl<T> Channel<T> {
     /// Constructs a new zero-capacity channel.
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Channel {
             inner: Spinlock::new(Inner {
                 senders: Waker::new(),
@@ -102,12 +102,12 @@ impl<T> Channel<T> {
     }
 
     /// Returns a receiver handle to the channel.
-    pub fn receiver(&self) -> Receiver<'_, T> {
+    pub(crate) fn receiver(&self) -> Receiver<'_, T> {
         Receiver(self)
     }
 
     /// Returns a sender handle to the channel.
-    pub fn sender(&self) -> Sender<'_, T> {
+    pub(crate) fn sender(&self) -> Sender<'_, T> {
         Sender(self)
     }
 
@@ -128,7 +128,7 @@ impl<T> Channel<T> {
     }
 
     /// Writes a message into the packet.
-    pub unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
+    pub(crate) unsafe fn write(&self, token: &mut Token, msg: T) -> Result<(), T> {
         // If there is no packet, the channel is disconnected.
         if token.zero == 0 {
             return Err(msg);
@@ -157,7 +157,7 @@ impl<T> Channel<T> {
     }
 
     /// Reads a message from the packet.
-    pub unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
+    pub(crate) unsafe fn read(&self, token: &mut Token) -> Result<T, ()> {
         // If there is no packet, the channel is disconnected.
         if token.zero == 0 {
             return Err(());
@@ -183,7 +183,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to send a message into the channel.
-    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
+    pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
         let token = &mut Token::default();
         let mut inner = self.inner.lock();
 
@@ -203,7 +203,11 @@ impl<T> Channel<T> {
     }
 
     /// Sends a message into the channel.
-    pub fn send(&self, msg: T, deadline: Option<Instant>) -> Result<(), SendTimeoutError<T>> {
+    pub(crate) fn send(
+        &self,
+        msg: T,
+        deadline: Option<Instant>,
+    ) -> Result<(), SendTimeoutError<T>> {
         let token = &mut Token::default();
         let mut inner = self.inner.lock();
 
@@ -256,7 +260,7 @@ impl<T> Channel<T> {
     }
 
     /// Attempts to receive a message without blocking.
-    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+    pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
         let token = &mut Token::default();
         let mut inner = self.inner.lock();
 
@@ -273,7 +277,7 @@ impl<T> Channel<T> {
     }
 
     /// Receives a message from the channel.
-    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
+    pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
         let token = &mut Token::default();
         let mut inner = self.inner.lock();
 
@@ -325,7 +329,7 @@ impl<T> Channel<T> {
     /// Disconnects the channel and wakes up all blocked senders and receivers.
     ///
     /// Returns `true` if this call disconnected the channel.
-    pub fn disconnect(&self) -> bool {
+    pub(crate) fn disconnect(&self) -> bool {
         let mut inner = self.inner.lock();
 
         if !inner.is_disconnected {
@@ -339,31 +343,32 @@ impl<T> Channel<T> {
     }
 
     /// Returns the current number of messages inside the channel.
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         0
     }
 
     /// Returns the capacity of the channel.
-    pub fn capacity(&self) -> Option<usize> {
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
+    pub(crate) fn capacity(&self) -> Option<usize> {
         Some(0)
     }
 
     /// Returns `true` if the channel is empty.
-    pub fn is_empty(&self) -> bool {
+    pub(crate) fn is_empty(&self) -> bool {
         true
     }
 
     /// Returns `true` if the channel is full.
-    pub fn is_full(&self) -> bool {
+    pub(crate) fn is_full(&self) -> bool {
         true
     }
 }
 
 /// Receiver handle to a channel.
-pub struct Receiver<'a, T>(&'a Channel<T>);
+pub(crate) struct Receiver<'a, T>(&'a Channel<T>);
 
 /// Sender handle to a channel.
-pub struct Sender<'a, T>(&'a Channel<T>);
+pub(crate) struct Sender<'a, T>(&'a Channel<T>);
 
 impl<T> SelectHandle for Receiver<'_, T> {
     fn try_select(&self, token: &mut Token) -> bool {
diff --git a/third_party/rust/crossbeam-channel/src/lib.rs b/third_party/rust/crossbeam-channel/src/lib.rs
index e08ac08f9088e64c61aa742277b1fea2629d20b7..cc1ef112f9cce971affcd0b84d7317725626c215 100644
--- a/third_party/rust/crossbeam-channel/src/lib.rs
+++ b/third_party/rust/crossbeam-channel/src/lib.rs
@@ -294,7 +294,7 @@
 //!
 //! * [`after`] creates a channel that delivers a single message after a certain duration of time.
 //! * [`tick`] creates a channel that delivers messages periodically.
-//! * [`never`] creates a channel that never delivers messages.
+//! * [`never`](never()) creates a channel that never delivers messages.
 //!
 //! These channels are very efficient because messages get lazily generated on receive operations.
 //!
@@ -328,10 +328,13 @@
         allow(dead_code, unused_assignments, unused_variables)
     )
 ))]
-#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
+#![warn(
+    missing_docs,
+    missing_debug_implementations,
+    rust_2018_idioms,
+    unreachable_pub
+)]
 #![cfg_attr(not(feature = "std"), no_std)]
-// matches! requires Rust 1.42
-#![allow(clippy::match_like_matches_macro)]
 
 use cfg_if::cfg_if;
 
diff --git a/third_party/rust/crossbeam-channel/src/select.rs b/third_party/rust/crossbeam-channel/src/select.rs
index 1488f80d5f46915c18b666371e0b774cac533016..5259328b805762a31606e3c0696660bcbb5344ad 100644
--- a/third_party/rust/crossbeam-channel/src/select.rs
+++ b/third_party/rust/crossbeam-channel/src/select.rs
@@ -486,7 +486,7 @@ pub fn select_timeout<'a>(
 
 /// Blocks until a given deadline, or until one of the operations becomes ready and selects it.
 #[inline]
-pub fn select_deadline<'a>(
+pub(crate) fn select_deadline<'a>(
     handles: &mut [(&'a dyn SelectHandle, usize, *const u8)],
     deadline: Instant,
 ) -> Result<SelectedOperation<'a>, SelectTimeoutError> {
@@ -864,9 +864,6 @@ impl<'a> Select<'a> {
     /// The selected operation must be completed with [`SelectedOperation::send`]
     /// or [`SelectedOperation::recv`].
     ///
-    /// [`SelectedOperation::send`]: struct.SelectedOperation.html#method.send
-    /// [`SelectedOperation::recv`]: struct.SelectedOperation.html#method.recv
-    ///
     /// # Examples
     ///
     /// ```
diff --git a/third_party/rust/crossbeam-channel/src/utils.rs b/third_party/rust/crossbeam-channel/src/utils.rs
index 3fe171b2e45291dae52e34756c92dfb16c3b84a2..557b6a0d771d2611fc55241dbf0c7ebd7a73f09c 100644
--- a/third_party/rust/crossbeam-channel/src/utils.rs
+++ b/third_party/rust/crossbeam-channel/src/utils.rs
@@ -10,7 +10,7 @@ use std::time::{Duration, Instant};
 use crossbeam_utils::Backoff;
 
 /// Randomly shuffles a slice.
-pub fn shuffle<T>(v: &mut [T]) {
+pub(crate) fn shuffle<T>(v: &mut [T]) {
     let len = v.len();
     if len <= 1 {
         return;
@@ -46,7 +46,7 @@ pub fn shuffle<T>(v: &mut [T]) {
 }
 
 /// Sleeps until the deadline, or forever if the deadline isn't specified.
-pub fn sleep_until(deadline: Option<Instant>) {
+pub(crate) fn sleep_until(deadline: Option<Instant>) {
     loop {
         match deadline {
             None => thread::sleep(Duration::from_secs(1000)),
@@ -62,14 +62,14 @@ pub fn sleep_until(deadline: Option<Instant>) {
 }
 
 /// A simple spinlock.
-pub struct Spinlock<T> {
+pub(crate) struct Spinlock<T> {
     flag: AtomicBool,
     value: UnsafeCell<T>,
 }
 
 impl<T> Spinlock<T> {
     /// Returns a new spinlock initialized with `value`.
-    pub fn new(value: T) -> Spinlock<T> {
+    pub(crate) fn new(value: T) -> Spinlock<T> {
         Spinlock {
             flag: AtomicBool::new(false),
             value: UnsafeCell::new(value),
@@ -77,7 +77,7 @@ impl<T> Spinlock<T> {
     }
 
     /// Locks the spinlock.
-    pub fn lock(&self) -> SpinlockGuard<'_, T> {
+    pub(crate) fn lock(&self) -> SpinlockGuard<'_, T> {
         let backoff = Backoff::new();
         while self.flag.swap(true, Ordering::Acquire) {
             backoff.snooze();
@@ -87,7 +87,7 @@ impl<T> Spinlock<T> {
 }
 
 /// A guard holding a spinlock locked.
-pub struct SpinlockGuard<'a, T> {
+pub(crate) struct SpinlockGuard<'a, T> {
     parent: &'a Spinlock<T>,
 }
 
diff --git a/third_party/rust/crossbeam-channel/src/waker.rs b/third_party/rust/crossbeam-channel/src/waker.rs
index 3d0af2616cc4405e54b276a5005f7e82ca0bdeb6..62defa2e18439dc4216807c9147fca2438975857 100644
--- a/third_party/rust/crossbeam-channel/src/waker.rs
+++ b/third_party/rust/crossbeam-channel/src/waker.rs
@@ -8,22 +8,22 @@ use crate::select::{Operation, Selected};
 use crate::utils::Spinlock;
 
 /// Represents a thread blocked on a specific channel operation.
-pub struct Entry {
+pub(crate) struct Entry {
     /// The operation.
-    pub oper: Operation,
+    pub(crate) oper: Operation,
 
     /// Optional packet.
-    pub packet: usize,
+    pub(crate) packet: usize,
 
     /// Context associated with the thread owning this operation.
-    pub cx: Context,
+    pub(crate) cx: Context,
 }
 
 /// A queue of threads blocked on channel operations.
 ///
 /// This data structure is used by threads to register blocking operations and get woken up once
 /// an operation becomes ready.
-pub struct Waker {
+pub(crate) struct Waker {
     /// A list of select operations.
     selectors: Vec<Entry>,
 
@@ -34,7 +34,7 @@ pub struct Waker {
 impl Waker {
     /// Creates a new `Waker`.
     #[inline]
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         Waker {
             selectors: Vec::new(),
             observers: Vec::new(),
@@ -43,13 +43,13 @@ impl Waker {
 
     /// Registers a select operation.
     #[inline]
-    pub fn register(&mut self, oper: Operation, cx: &Context) {
+    pub(crate) fn register(&mut self, oper: Operation, cx: &Context) {
         self.register_with_packet(oper, 0, cx);
     }
 
     /// Registers a select operation and a packet.
     #[inline]
-    pub fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
+    pub(crate) fn register_with_packet(&mut self, oper: Operation, packet: usize, cx: &Context) {
         self.selectors.push(Entry {
             oper,
             packet,
@@ -59,7 +59,7 @@ impl Waker {
 
     /// Unregisters a select operation.
     #[inline]
-    pub fn unregister(&mut self, oper: Operation) -> Option<Entry> {
+    pub(crate) fn unregister(&mut self, oper: Operation) -> Option<Entry> {
         if let Some((i, _)) = self
             .selectors
             .iter()
@@ -75,7 +75,7 @@ impl Waker {
 
     /// Attempts to find another thread's entry, select the operation, and wake it up.
     #[inline]
-    pub fn try_select(&mut self) -> Option<Entry> {
+    pub(crate) fn try_select(&mut self) -> Option<Entry> {
         let mut entry = None;
 
         if !self.selectors.is_empty() {
@@ -108,7 +108,7 @@ impl Waker {
 
     /// Returns `true` if there is an entry which can be selected by the current thread.
     #[inline]
-    pub fn can_select(&self) -> bool {
+    pub(crate) fn can_select(&self) -> bool {
         if self.selectors.is_empty() {
             false
         } else {
@@ -122,7 +122,7 @@ impl Waker {
 
     /// Registers an operation waiting to be ready.
     #[inline]
-    pub fn watch(&mut self, oper: Operation, cx: &Context) {
+    pub(crate) fn watch(&mut self, oper: Operation, cx: &Context) {
         self.observers.push(Entry {
             oper,
             packet: 0,
@@ -132,13 +132,13 @@ impl Waker {
 
     /// Unregisters an operation waiting to be ready.
     #[inline]
-    pub fn unwatch(&mut self, oper: Operation) {
+    pub(crate) fn unwatch(&mut self, oper: Operation) {
         self.observers.retain(|e| e.oper != oper);
     }
 
     /// Notifies all operations waiting to be ready.
     #[inline]
-    pub fn notify(&mut self) {
+    pub(crate) fn notify(&mut self) {
         for entry in self.observers.drain(..) {
             if entry.cx.try_select(Selected::Operation(entry.oper)).is_ok() {
                 entry.cx.unpark();
@@ -148,7 +148,7 @@ impl Waker {
 
     /// Notifies all registered operations that the channel is disconnected.
     #[inline]
-    pub fn disconnect(&mut self) {
+    pub(crate) fn disconnect(&mut self) {
         for entry in self.selectors.iter() {
             if entry.cx.try_select(Selected::Disconnected).is_ok() {
                 // Wake the thread up.
@@ -175,7 +175,7 @@ impl Drop for Waker {
 /// A waker that can be shared among threads without locking.
 ///
 /// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
-pub struct SyncWaker {
+pub(crate) struct SyncWaker {
     /// The inner `Waker`.
     inner: Spinlock<Waker>,
 
@@ -186,7 +186,7 @@ pub struct SyncWaker {
 impl SyncWaker {
     /// Creates a new `SyncWaker`.
     #[inline]
-    pub fn new() -> Self {
+    pub(crate) fn new() -> Self {
         SyncWaker {
             inner: Spinlock::new(Waker::new()),
             is_empty: AtomicBool::new(true),
@@ -195,7 +195,7 @@ impl SyncWaker {
 
     /// Registers the current thread with an operation.
     #[inline]
-    pub fn register(&self, oper: Operation, cx: &Context) {
+    pub(crate) fn register(&self, oper: Operation, cx: &Context) {
         let mut inner = self.inner.lock();
         inner.register(oper, cx);
         self.is_empty.store(
@@ -206,7 +206,7 @@ impl SyncWaker {
 
     /// Unregisters an operation previously registered by the current thread.
     #[inline]
-    pub fn unregister(&self, oper: Operation) -> Option<Entry> {
+    pub(crate) fn unregister(&self, oper: Operation) -> Option<Entry> {
         let mut inner = self.inner.lock();
         let entry = inner.unregister(oper);
         self.is_empty.store(
@@ -218,7 +218,7 @@ impl SyncWaker {
 
     /// Attempts to find one thread (not the current one), select its operation, and wake it up.
     #[inline]
-    pub fn notify(&self) {
+    pub(crate) fn notify(&self) {
         if !self.is_empty.load(Ordering::SeqCst) {
             let mut inner = self.inner.lock();
             if !self.is_empty.load(Ordering::SeqCst) {
@@ -234,7 +234,7 @@ impl SyncWaker {
 
     /// Registers an operation waiting to be ready.
     #[inline]
-    pub fn watch(&self, oper: Operation, cx: &Context) {
+    pub(crate) fn watch(&self, oper: Operation, cx: &Context) {
         let mut inner = self.inner.lock();
         inner.watch(oper, cx);
         self.is_empty.store(
@@ -245,7 +245,7 @@ impl SyncWaker {
 
     /// Unregisters an operation waiting to be ready.
     #[inline]
-    pub fn unwatch(&self, oper: Operation) {
+    pub(crate) fn unwatch(&self, oper: Operation) {
         let mut inner = self.inner.lock();
         inner.unwatch(oper);
         self.is_empty.store(
@@ -256,7 +256,7 @@ impl SyncWaker {
 
     /// Notifies all threads that the channel is disconnected.
     #[inline]
-    pub fn disconnect(&self) {
+    pub(crate) fn disconnect(&self) {
         let mut inner = self.inner.lock();
         inner.disconnect();
         self.is_empty.store(
diff --git a/third_party/rust/crossbeam-channel/tests/array.rs b/third_party/rust/crossbeam-channel/tests/array.rs
index a7ae323d91af0f70c14798e872804e2798e197c7..15c30a50b16a34181f33000a39e8fe1da71e553a 100644
--- a/third_party/rust/crossbeam-channel/tests/array.rs
+++ b/third_party/rust/crossbeam-channel/tests/array.rs
@@ -497,8 +497,8 @@ fn drops() {
     let mut rng = thread_rng();
 
     for _ in 0..RUNS {
-        let steps = rng.gen_range(0, 10_000);
-        let additional = rng.gen_range(0, 50);
+        let steps = rng.gen_range(0..10_000);
+        let additional = rng.gen_range(0..50);
 
         DROPS.store(0, Ordering::SeqCst);
         let (s, r) = bounded::<DropCounter>(50);
diff --git a/third_party/rust/crossbeam-channel/tests/golang.rs b/third_party/rust/crossbeam-channel/tests/golang.rs
index 69a9315a0a58c583d4242bd86e9adcd59a8000c0..cd7001326f685ad35a19a0b13dcaa6cfb3c3ef3a 100644
--- a/third_party/rust/crossbeam-channel/tests/golang.rs
+++ b/third_party/rust/crossbeam-channel/tests/golang.rs
@@ -315,7 +315,7 @@ mod fifo {
     fn chain(ch: Chan<i32>, val: i32, inp: Chan<i32>, out: Chan<i32>) {
         inp.recv();
         if ch.recv() != Some(val) {
-            panic!(val);
+            panic!("{}", val);
         }
         out.send(1);
     }
@@ -1507,5 +1507,58 @@ mod chan {
 
 // https://github.com/golang/go/blob/master/test/ken/chan1.go
 mod chan1 {
-    // TODO
+    use super::*;
+
+    // sent messages
+    const N: usize = 1000;
+    // receiving "goroutines"
+    const M: usize = 10;
+    // channel buffering
+    const W: usize = 2;
+
+    fn r(c: Chan<usize>, m: usize, h: Arc<Mutex<[usize; N]>>) {
+        loop {
+            select! {
+                recv(c.rx()) -> rr => {
+                    let r = rr.unwrap();
+                    let mut data = h.lock().unwrap();
+                    if data[r] != 1 {
+                        println!("r\nm={}\nr={}\nh={}\n", m, r, data[r]);
+                        panic!("fail")
+                    }
+                    data[r] = 2;
+                }
+            }
+        }
+    }
+
+    fn s(c: Chan<usize>, h: Arc<Mutex<[usize; N]>>) {
+        for n in 0..N {
+            let r = n;
+            let mut data = h.lock().unwrap();
+            if data[r] != 0 {
+                println!("s");
+                panic!("fail");
+            }
+            data[r] = 1;
+            // https://github.com/crossbeam-rs/crossbeam/pull/615#discussion_r550281094
+            drop(data);
+            c.send(r);
+        }
+    }
+
+    #[test]
+    fn main() {
+        let h = Arc::new(Mutex::new([0usize; N]));
+        let c = make::<usize>(W);
+        for m in 0..M {
+            go!(c, h, {
+                r(c, m, h);
+            });
+            thread::yield_now();
+        }
+        thread::yield_now();
+        thread::yield_now();
+        s(c, h);
+    }
 }
diff --git a/third_party/rust/crossbeam-channel/tests/list.rs b/third_party/rust/crossbeam-channel/tests/list.rs
index 8b841054067c5dc0ceac120d8884cc870edca34e..f166a19815f5a548da40bd2cfd134e1d70390dd2 100644
--- a/third_party/rust/crossbeam-channel/tests/list.rs
+++ b/third_party/rust/crossbeam-channel/tests/list.rs
@@ -387,8 +387,8 @@ fn drops() {
     let mut rng = thread_rng();
 
     for _ in 0..100 {
-        let steps = rng.gen_range(0, 10_000);
-        let additional = rng.gen_range(0, 1000);
+        let steps = rng.gen_range(0..10_000);
+        let additional = rng.gen_range(0..1000);
 
         DROPS.store(0, Ordering::SeqCst);
         let (s, r) = unbounded::<DropCounter>();
diff --git a/third_party/rust/crossbeam-channel/tests/ready.rs b/third_party/rust/crossbeam-channel/tests/ready.rs
index 700f487e04174c113a4739ec92ce8606198a805a..6779694a978a920a47f74d0c0e1a70f588307536 100644
--- a/third_party/rust/crossbeam-channel/tests/ready.rs
+++ b/third_party/rust/crossbeam-channel/tests/ready.rs
@@ -606,8 +606,7 @@ fn stress_timeout_two_threads() {
                     thread::sleep(ms(500));
                 }
 
-                let done = false;
-                while !done {
+                loop {
                     let mut sel = Select::new();
                     sel.send(&s);
                     match sel.ready_timeout(ms(100)) {
@@ -628,15 +627,14 @@ fn stress_timeout_two_threads() {
                     thread::sleep(ms(500));
                 }
 
-                let mut done = false;
-                while !done {
+                loop {
                     let mut sel = Select::new();
                     sel.recv(&r);
                     match sel.ready_timeout(ms(100)) {
                         Err(_) => {}
                         Ok(0) => {
                             assert_eq!(r.try_recv(), Ok(i));
-                            done = true;
+                            break;
                         }
                         Ok(_) => panic!(),
                     }
diff --git a/third_party/rust/crossbeam-channel/tests/select.rs b/third_party/rust/crossbeam-channel/tests/select.rs
index 4cf08b6a6282e2ba94d038ace4e0b8aae8b139be..fcc291ef382994a7a3e51d30240e1566b9dbfc55 100644
--- a/third_party/rust/crossbeam-channel/tests/select.rs
+++ b/third_party/rust/crossbeam-channel/tests/select.rs
@@ -809,8 +809,7 @@ fn stress_timeout_two_threads() {
                     thread::sleep(ms(500));
                 }
 
-                let done = false;
-                while !done {
+                loop {
                     let mut sel = Select::new();
                     let oper1 = sel.send(&s);
                     let oper = sel.select_timeout(ms(100));
@@ -834,8 +833,7 @@ fn stress_timeout_two_threads() {
                     thread::sleep(ms(500));
                 }
 
-                let mut done = false;
-                while !done {
+                loop {
                     let mut sel = Select::new();
                     let oper1 = sel.recv(&r);
                     let oper = sel.select_timeout(ms(100));
@@ -844,7 +842,7 @@ fn stress_timeout_two_threads() {
                         Ok(oper) => match oper.index() {
                             ix if ix == oper1 => {
                                 assert_eq!(oper.recv(&r), Ok(i));
-                                done = true;
+                                break;
                             }
                             _ => unreachable!(),
                         },
diff --git a/third_party/rust/crossbeam-channel/tests/tick.rs b/third_party/rust/crossbeam-channel/tests/tick.rs
index 5dc87306ff357681a138d19b84f0ff4fa9ca7acd..1273f64b5b044246e6a78727b04c426b958d7f0f 100644
--- a/third_party/rust/crossbeam-channel/tests/tick.rs
+++ b/third_party/rust/crossbeam-channel/tests/tick.rs
@@ -127,6 +127,7 @@ fn recv() {
     assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
 }
 
+#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
 #[test]
 fn recv_timeout() {
     let start = Instant::now();
@@ -251,6 +252,7 @@ fn select() {
     assert_eq!(hits.load(Ordering::SeqCst), 8);
 }
 
+#[cfg(not(crossbeam_sanitize))] // TODO: assertions failed due to tsan is slow
 #[test]
 fn ready() {
     const THREADS: usize = 4;
diff --git a/third_party/rust/crossbeam-channel/tests/zero.rs b/third_party/rust/crossbeam-channel/tests/zero.rs
index 66dcc1eeb6614370789ed4952e83abb5f2f86e98..1dd39e1817399026f2d1e69d718e2d7871392499 100644
--- a/third_party/rust/crossbeam-channel/tests/zero.rs
+++ b/third_party/rust/crossbeam-channel/tests/zero.rs
@@ -399,7 +399,7 @@ fn drops() {
     let mut rng = thread_rng();
 
     for _ in 0..100 {
-        let steps = rng.gen_range(0, 3_000);
+        let steps = rng.gen_range(0..3_000);
 
         DROPS.store(0, Ordering::SeqCst);
         let (s, r) = bounded::<DropCounter>(0);
diff --git a/third_party/rust/crossbeam-deque/.cargo-checksum.json b/third_party/rust/crossbeam-deque/.cargo-checksum.json
index 76bc64238e6ad4ba01ee068b7c4d52c3c2ae2635..202fdfe8de291b1e7b0a8797f18326f445257413 100644
--- a/third_party/rust/crossbeam-deque/.cargo-checksum.json
+++ b/third_party/rust/crossbeam-deque/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"2a351fc7603e0cf7a66c305fa9429f7871113605427a8e43f701b71854cc2181","Cargo.toml":"381453938bdca74a67ac96146f8c544b30aa62293e47eaa6447a9d9bb03668eb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"c1e2f0e311bab5c2b82a9346e7b2fdaf17050a66913aad57fac40665fb65bb7b","src/lib.rs":"279ea1d9e7e72488e2590cb88fb14bdf9b8250676adb27d19efd281c91e63680","tests/fifo.rs":"7546ce471330a9d928a54f6ca41ddd36e9f4999852fdc4719bf9b24122a1c15f","tests/injector.rs":"c9107b437f790dbfab333f94d7211df29bb9a868d2d86304ad9fd7fa8db57d0a","tests/lifo.rs":"264967bc868870211e12a826f448a6d9e19ab5f7cc0e0bde86496cf76bb96e56","tests/steal.rs":"519549c18429db563c5238d7147e733901336943ca099669af2b553933b82694"},"package":"c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"f917b6e83aed21fcdb7615602b74377374144b6e075d1d96e9dac8c266795cab","Cargo.toml":"d160e0a9f564fa20e503f81a837057b09bdc8632d8b71c6a3d4a0a67c0bcaa21","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"c1e2f0e311bab5c2b82a9346e7b2fdaf17050a66913aad57fac40665fb65bb7b","src/lib.rs":"78b31a8d769607304d5d6250f8b06f257160b7c8b43ced5ef40f4ec3a51e076b","tests/fifo.rs":"7546ce471330a9d928a54f6ca41ddd36e9f4999852fdc4719bf9b24122a1c15f","tests/injector.rs":"c9107b437f790dbfab333f94d7211df29bb9a868d2d86304ad9fd7fa8db57d0a","tests/lifo.rs":"264967bc868870211e12a826f448a6d9e19ab5f7cc0e0bde86496cf76bb96e56","tests/steal.rs":"519549c18429db563c5238d7147e733901336943ca099669af2b553933b82694"},"package":"9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-deque/CHANGELOG.md b/third_party/rust/crossbeam-deque/CHANGELOG.md
index a9e1c79a8837ebd8d9c1eeee0a1d134136b2f945..54e9ae41fcbd083d92a0ddf9ab3777b11e93c8bf 100644
--- a/third_party/rust/crossbeam-deque/CHANGELOG.md
+++ b/third_party/rust/crossbeam-deque/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Version 0.7.3
+
+- Stop stealing from the same deque. (#448)
+- Fix unsoundness issues by adopting `MaybeUninit`. (#458)
+
 # Version 0.7.2
 
 - Bump `crossbeam-epoch` to `0.8`.
diff --git a/third_party/rust/crossbeam-deque/Cargo.toml b/third_party/rust/crossbeam-deque/Cargo.toml
index 2ce052337fd6a165f8f22f8021eb74c76f60d0aa..0cf94c2df5732f6fa9a4427a72e694127b8ddca4 100644
--- a/third_party/rust/crossbeam-deque/Cargo.toml
+++ b/third_party/rust/crossbeam-deque/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "crossbeam-deque"
-version = "0.7.2"
+version = "0.7.3"
 authors = ["The Crossbeam Project Developers"]
 description = "Concurrent work-stealing deque"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-deque"
@@ -27,5 +27,8 @@ version = "0.8"
 
 [dependencies.crossbeam-utils]
 version = "0.7"
+
+[dependencies.maybe-uninit]
+version = "2.0.0"
 [dev-dependencies.rand]
 version = "0.6"
diff --git a/third_party/rust/crossbeam-deque/src/lib.rs b/third_party/rust/crossbeam-deque/src/lib.rs
index 1fdf00e3dccacd306b0af74f086199db74202cac..59004174d83b6c52a9ad5fba2d4fefc4c2301b07 100644
--- a/third_party/rust/crossbeam-deque/src/lib.rs
+++ b/third_party/rust/crossbeam-deque/src/lib.rs
@@ -92,12 +92,14 @@
 extern crate crossbeam_epoch as epoch;
 extern crate crossbeam_utils as utils;
 
+extern crate maybe_uninit;
+
 use std::cell::{Cell, UnsafeCell};
 use std::cmp;
 use std::fmt;
 use std::iter::FromIterator;
 use std::marker::PhantomData;
-use std::mem::{self, ManuallyDrop};
+use std::mem;
 use std::ptr;
 use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering};
 use std::sync::Arc;
@@ -105,6 +107,8 @@ use std::sync::Arc;
 use epoch::{Atomic, Owned};
 use utils::{Backoff, CachePadded};
 
+use maybe_uninit::MaybeUninit;
+
 // Minimum buffer capacity.
 const MIN_CAP: usize = 64;
 // Maximum number of tasks that can be stolen in `steal_batch()` and `steal_batch_and_pop()`.
@@ -218,7 +222,7 @@ impl<T> Drop for Inner<T> {
             // Go through the buffer from front to back and drop all tasks in the queue.
             let mut i = f;
             while i != b {
-                ptr::drop_in_place(buffer.deref().at(i));
+                buffer.deref().at(i).drop_in_place();
                 i = i.wrapping_add(1);
             }
 
@@ -745,6 +749,14 @@ impl<T> Stealer<T> {
     /// assert_eq!(w2.pop(), Some(2));
     /// ```
     pub fn steal_batch(&self, dest: &Worker<T>) -> Steal<()> {
+        if Arc::ptr_eq(&self.inner, &dest.inner) {
+            if dest.is_empty() {
+                return Steal::Empty;
+            } else {
+                return Steal::Success(());
+            }
+        }
+
         // Load the front index.
         let mut f = self.inner.front.load(Ordering::Acquire);
 
@@ -922,6 +934,13 @@ impl<T> Stealer<T> {
     /// assert_eq!(w2.pop(), Some(2));
     /// ```
     pub fn steal_batch_and_pop(&self, dest: &Worker<T>) -> Steal<T> {
+        if Arc::ptr_eq(&self.inner, &dest.inner) {
+            match dest.pop() {
+                None => return Steal::Empty,
+                Some(task) => return Steal::Success(task),
+            }
+        }
+
         // Load the front index.
         let mut f = self.inner.front.load(Ordering::Acquire);
 
@@ -1125,7 +1144,7 @@ const HAS_NEXT: usize = 1;
 /// A slot in a block.
 struct Slot<T> {
     /// The task.
-    task: UnsafeCell<ManuallyDrop<T>>,
+    task: UnsafeCell<MaybeUninit<T>>,
 
     /// The state of the slot.
     state: AtomicUsize,
@@ -1155,7 +1174,13 @@ struct Block<T> {
 impl<T> Block<T> {
     /// Creates an empty block that starts at `start_index`.
     fn new() -> Block<T> {
-        unsafe { mem::zeroed() }
+        // SAFETY: This is safe because:
+        //  [1] `Block::next` (AtomicPtr) may be safely zero initialized.
+        //  [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
+        //  [3] `Slot::task` (UnsafeCell) may be safely zero initialized because it
+        //       holds a MaybeUninit.
+        //  [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
+        unsafe { MaybeUninit::zeroed().assume_init() }
     }
 
     /// Waits until the next pointer is set.
@@ -1314,7 +1339,7 @@ impl<T> Injector<T> {
 
                     // Write the task into the slot.
                     let slot = (*block).slots.get_unchecked(offset);
-                    slot.task.get().write(ManuallyDrop::new(task));
+                    slot.task.get().write(MaybeUninit::new(task));
                     slot.state.fetch_or(WRITE, Ordering::Release);
 
                     return;
@@ -1407,8 +1432,7 @@ impl<T> Injector<T> {
             // Read the task.
             let slot = (*block).slots.get_unchecked(offset);
             slot.wait_write();
-            let m = slot.task.get().read();
-            let task = ManuallyDrop::into_inner(m);
+            let task = slot.task.get().read().assume_init();
 
             // Destroy the block if we've reached the end, or if another thread wanted to destroy
             // but couldn't because we were busy reading from the slot.
@@ -1533,8 +1557,7 @@ impl<T> Injector<T> {
                         // Read the task.
                         let slot = (*block).slots.get_unchecked(offset + i);
                         slot.wait_write();
-                        let m = slot.task.get().read();
-                        let task = ManuallyDrop::into_inner(m);
+                        let task = slot.task.get().read().assume_init();
 
                         // Write it into the destination queue.
                         dest_buffer.write(dest_b.wrapping_add(i as isize), task);
@@ -1546,8 +1569,7 @@ impl<T> Injector<T> {
                         // Read the task.
                         let slot = (*block).slots.get_unchecked(offset + i);
                         slot.wait_write();
-                        let m = slot.task.get().read();
-                        let task = ManuallyDrop::into_inner(m);
+                        let task = slot.task.get().read().assume_init();
 
                         // Write it into the destination queue.
                         dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task);
@@ -1689,8 +1711,7 @@ impl<T> Injector<T> {
             // Read the task.
             let slot = (*block).slots.get_unchecked(offset);
             slot.wait_write();
-            let m = slot.task.get().read();
-            let task = ManuallyDrop::into_inner(m);
+            let task = slot.task.get().read().assume_init();
 
             match dest.flavor {
                 Flavor::Fifo => {
@@ -1699,8 +1720,7 @@ impl<T> Injector<T> {
                         // Read the task.
                         let slot = (*block).slots.get_unchecked(offset + i + 1);
                         slot.wait_write();
-                        let m = slot.task.get().read();
-                        let task = ManuallyDrop::into_inner(m);
+                        let task = slot.task.get().read().assume_init();
 
                         // Write it into the destination queue.
                         dest_buffer.write(dest_b.wrapping_add(i as isize), task);
@@ -1713,8 +1733,7 @@ impl<T> Injector<T> {
                         // Read the task.
                         let slot = (*block).slots.get_unchecked(offset + i + 1);
                         slot.wait_write();
-                        let m = slot.task.get().read();
-                        let task = ManuallyDrop::into_inner(m);
+                        let task = slot.task.get().read().assume_init();
 
                         // Write it into the destination queue.
                         dest_buffer.write(dest_b.wrapping_add((batch_size - 1 - i) as isize), task);
@@ -1789,7 +1808,8 @@ impl<T> Drop for Injector<T> {
                 if offset < BLOCK_CAP {
                     // Drop the task in the slot.
                     let slot = (*block).slots.get_unchecked(offset);
-                    ManuallyDrop::drop(&mut *(*slot).task.get());
+                    let p = &mut *slot.task.get();
+                    p.as_mut_ptr().drop_in_place();
                 } else {
                     // Deallocate the block and move to the next one.
                     let next = (*block).next.load(Ordering::Relaxed);
diff --git a/third_party/rust/crossbeam-epoch/.cargo-checksum.json b/third_party/rust/crossbeam-epoch/.cargo-checksum.json
index d42d88919de49d68c8094d4d26e8bb549921fa3c..231351ab6983df9fcaefd72cb339be36011e7940 100644
--- a/third_party/rust/crossbeam-epoch/.cargo-checksum.json
+++ b/third_party/rust/crossbeam-epoch/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"1d5defc0cddbd56dab9aad0c52a6101e2ae38a04703622b70822af4162b422b6","Cargo.lock":"dd8ea5cc92174990a2726564d8ea7d4cf1dcbc0e5775a5a8f07b854bcb25e27d","Cargo.toml":"802dbfef2329ab8d39ce1602e93f41403e2c297521e702e4278cf88df106f3a4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"30bed3b95612935f87903eeb37dfd09e133e4c064a66eb8b5681eaf97128c8e9","benches/defer.rs":"a4b17e7b96bef2f268c76925cfa58744b81504146426fab6f781ff0b2f666f2b","benches/flush.rs":"1d93ac40cb78bf2c55332869d4f7d1b283571bff4a0c6dbe245f02dd65e8e1d8","benches/pin.rs":"dd937ecfc8d7353995d438a7f4be383e91c002e9ee6acd4caa703bb340c97383","build.rs":"825c47ae19028dc4b28101ec71c04e7e41b8b185f6ecbeacee223596524c86ad","examples/sanitize.rs":"90f80709cd620e994f699d84ab9ce88f8552500d08bac64d60def5792460495a","examples/treiber_stack.rs":"b5d3bafa6d57af435b00d04145572a51ea871f64ff2c23ba544054c4c4145d65","src/atomic.rs":"53c29c8df6a90e2cd3d7747f7ebfe604087966c8ea6473ff2593bdd495f43951","src/collector.rs":"a783049d3cb22989ec978366fd865f31562b0acbfbd0bc9ff9b600ceaa5ffa87","src/default.rs":"6afda8fd141ad594bed62baeb73f2e97c5ef33b051969a542bb908946fe39dd1","src/deferred.rs":"883067dd60b108baacaafc9024833c0ec08c6b5649b60c030ab9a59e952ccd06","src/epoch.rs":"76dd63356d5bc52e741883d39abb636e4ccb04d20499fb2a0ce797bb81aa4e91","src/guard.rs":"486efbc061b7f402f4c8a96abd1889aff4b28eb10347b65e538c39d539d919ad","src/internal.rs":"5b09661b12d93412140b2ee186ebb304891374e4c512b5bbc97cd015ec34c493","src/lib.rs":"e55b6c418970e3bbd265a21b9beaf2d8254f7f7799e9954edf4486666869e2aa","src/sync/list.rs":"43e09e9cf79d7cf95b5110051de9dd47ab7761e3bc90ea3be16c4cbabce6d4be","src/sync/mod.rs":"2da979ca3a2293f7626a2e6a9ab2fad758d92e3d2bed6cc712ef59eeeea87eab","src/sync/queue.rs":"266036a201222fe46b6674fa789b96dd8c385bf2c37135799fb9ba1fba53049a"},"package":"5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"6f63ac1fc542b3aac4b43cdcd4c1ec549e2afb50c03836d3ca10468531684b5f","Cargo.lock":"cde1950d5785b0962e84cd5e98ce6bbbc981c606c2e73601f060d488ec2bca5f","Cargo.toml":"212414f7fad97f2b0eabff851d380ea75d043d3b16266a54e4724da588cd648d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"30bed3b95612935f87903eeb37dfd09e133e4c064a66eb8b5681eaf97128c8e9","benches/defer.rs":"a4b17e7b96bef2f268c76925cfa58744b81504146426fab6f781ff0b2f666f2b","benches/flush.rs":"1d93ac40cb78bf2c55332869d4f7d1b283571bff4a0c6dbe245f02dd65e8e1d8","benches/pin.rs":"dd937ecfc8d7353995d438a7f4be383e91c002e9ee6acd4caa703bb340c97383","build.rs":"825c47ae19028dc4b28101ec71c04e7e41b8b185f6ecbeacee223596524c86ad","examples/sanitize.rs":"90f80709cd620e994f699d84ab9ce88f8552500d08bac64d60def5792460495a","examples/treiber_stack.rs":"b5d3bafa6d57af435b00d04145572a51ea871f64ff2c23ba544054c4c4145d65","src/atomic.rs":"53c29c8df6a90e2cd3d7747f7ebfe604087966c8ea6473ff2593bdd495f43951","src/collector.rs":"a783049d3cb22989ec978366fd865f31562b0acbfbd0bc9ff9b600ceaa5ffa87","src/default.rs":"7fec6d381ae0efab8c1539c78588f99b8fcd6551ac67740fcfd45be3405ca53a","src/deferred.rs":"2793f8a5d271e7a787f7e99bdff7b07488742704bd47721459f0bb5085e6b3ea","src/epoch.rs":"76dd63356d5bc52e741883d39abb636e4ccb04d20499fb2a0ce797bb81aa4e91","src/guard.rs":"486efbc061b7f402f4c8a96abd1889aff4b28eb10347b65e538c39d539d919ad","src/internal.rs":"82030dc0cdc30741b2ca840455d2074e9fc0b9186c043d18bcf54bab093ce083","src/lib.rs":"c6c94853766d307eb36f75e1f4feabe2b4b13659d20e11ea9b82b6472363ce9f","src/sync/list.rs":"ef59984162102d01279f6eb7ded52d923933287dd4d7785b758b049768a3c118","src/sync/mod.rs":"2da979ca3a2293f7626a2e6a9ab2fad758d92e3d2bed6cc712ef59eeeea87eab","src/sync/queue.rs":"89390788a53ee932dcd92221cd2a8db25fd52a1e0b2b1fb9bd4230dec9eadcac"},"package":"058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-epoch/CHANGELOG.md b/third_party/rust/crossbeam-epoch/CHANGELOG.md
index e4aa1fdb29649ba50c0e635ad8bf8c1754e107f1..07e64efebf3230965e3911183b57ffc847bbd4b0 100644
--- a/third_party/rust/crossbeam-epoch/CHANGELOG.md
+++ b/third_party/rust/crossbeam-epoch/CHANGELOG.md
@@ -1,3 +1,15 @@
+# Version 0.8.2
+
+- Fix bug in release (yanking 0.8.1)
+
+# Version 0.8.1
+
+- Bump `autocfg` dependency to version 1.0. (#460)
+- Reduce stall in list iteration. (#376)
+- Stop stealing from the same deque. (#448)
+- Fix unsoundness issues by adopting `MaybeUninit`. (#458)
+- Fix use-after-free in lock-free queue. (#466)
+
 # Version 0.8.0
 
 - Bump the minimum required version to 1.28.
diff --git a/third_party/rust/crossbeam-epoch/Cargo.lock b/third_party/rust/crossbeam-epoch/Cargo.lock
index 9f19f55e358f8d7f568dce72dfc033ececc524c6..d3f8334df2542aacae2433cd91d016925d779460 100644
--- a/third_party/rust/crossbeam-epoch/Cargo.lock
+++ b/third_party/rust/crossbeam-epoch/Cargo.lock
@@ -5,6 +5,11 @@ name = "autocfg"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "autocfg"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "bitflags"
 version = "1.2.1"
@@ -25,15 +30,16 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.8.0"
+version = "0.8.2"
 dependencies = [
- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -58,12 +64,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.2.65"
+version = "0.2.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "memoffset"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -75,7 +86,7 @@ version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -130,7 +141,7 @@ name = "rand_jitter"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -142,7 +153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -183,7 +194,7 @@ dependencies = [
 
 [[package]]
 name = "scopeguard"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -220,14 +231,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
 "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
+"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
 "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
 "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
-"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc"
+"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
+"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -240,7 +253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
+"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
diff --git a/third_party/rust/crossbeam-epoch/Cargo.toml b/third_party/rust/crossbeam-epoch/Cargo.toml
index 0cdcbbbcd02fb0f27903912f2686ffc77c72e24b..7d5c0943b99855497ec34af4ff0f21b2b45955f6 100644
--- a/third_party/rust/crossbeam-epoch/Cargo.toml
+++ b/third_party/rust/crossbeam-epoch/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "crossbeam-epoch"
-version = "0.8.0"
+version = "0.8.2"
 authors = ["The Crossbeam Project Developers"]
 description = "Epoch-based garbage collection"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch"
@@ -33,6 +33,9 @@ default-features = false
 version = "1"
 optional = true
 
+[dependencies.maybe-uninit]
+version = "2.0.0"
+
 [dependencies.memoffset]
 version = "0.5"
 
@@ -42,7 +45,7 @@ default-features = false
 [dev-dependencies.rand]
 version = "0.6"
 [build-dependencies.autocfg]
-version = "0.1.6"
+version = "1"
 
 [features]
 alloc = ["crossbeam-utils/alloc"]
diff --git a/third_party/rust/crossbeam-epoch/src/default.rs b/third_party/rust/crossbeam-epoch/src/default.rs
index 734a62428f6a9304858806c37ace6431a0e17142..870e590fa280ee547f70f69fcc5e4d04fe07d406 100644
--- a/third_party/rust/crossbeam-epoch/src/default.rs
+++ b/third_party/rust/crossbeam-epoch/src/default.rs
@@ -70,6 +70,7 @@ mod tests {
                 super::pin();
                 // At thread exit, `HANDLE` gets dropped first and `FOO` second.
             });
-        }).unwrap();
+        })
+        .unwrap();
     }
 }
diff --git a/third_party/rust/crossbeam-epoch/src/deferred.rs b/third_party/rust/crossbeam-epoch/src/deferred.rs
index 3d22ee633ea34abf1065705bddb4c3f70b2b0815..a0970f1157a038b1605f2a64d5cd57ba7acdec05 100644
--- a/third_party/rust/crossbeam-epoch/src/deferred.rs
+++ b/third_party/rust/crossbeam-epoch/src/deferred.rs
@@ -4,6 +4,8 @@ use core::marker::PhantomData;
 use core::mem;
 use core::ptr;
 
+use maybe_uninit::MaybeUninit;
+
 /// Number of words a piece of `Data` can hold.
 ///
 /// Three words should be enough for the majority of cases. For example, you can fit inside it the
@@ -36,11 +38,8 @@ impl Deferred {
 
         unsafe {
             if size <= mem::size_of::<Data>() && align <= mem::align_of::<Data>() {
-                // TODO(taiki-e): when the minimum supported Rust version is bumped to 1.36+,
-                // replace this with `mem::MaybeUninit`.
-                #[allow(deprecated)]
-                let mut data: Data = mem::uninitialized();
-                ptr::write(&mut data as *mut Data as *mut F, f);
+                let mut data = MaybeUninit::<Data>::uninit();
+                ptr::write(data.as_mut_ptr() as *mut F, f);
 
                 unsafe fn call<F: FnOnce()>(raw: *mut u8) {
                     let f: F = ptr::read(raw as *mut F);
@@ -49,16 +48,13 @@ impl Deferred {
 
                 Deferred {
                     call: call::<F>,
-                    data,
+                    data: data.assume_init(),
                     _marker: PhantomData,
                 }
             } else {
                 let b: Box<F> = Box::new(f);
-                // TODO(taiki-e): when the minimum supported Rust version is bumped to 1.36+,
-                // replace this with `mem::MaybeUninit`.
-                #[allow(deprecated)]
-                let mut data: Data = mem::uninitialized();
-                ptr::write(&mut data as *mut Data as *mut Box<F>, b);
+                let mut data = MaybeUninit::<Data>::uninit();
+                ptr::write(data.as_mut_ptr() as *mut Box<F>, b);
 
                 unsafe fn call<F: FnOnce()>(raw: *mut u8) {
                     let b: Box<F> = ptr::read(raw as *mut Box<F>);
@@ -67,7 +63,7 @@ impl Deferred {
 
                 Deferred {
                     call: call::<F>,
-                    data,
+                    data: data.assume_init(),
                     _marker: PhantomData,
                 }
             }
diff --git a/third_party/rust/crossbeam-epoch/src/internal.rs b/third_party/rust/crossbeam-epoch/src/internal.rs
index 22038f30da2681334244067e8aed811c97b67bca..645511b9c8524cd4a1124af24a902987ed8373e5 100644
--- a/third_party/rust/crossbeam-epoch/src/internal.rs
+++ b/third_party/rust/crossbeam-epoch/src/internal.rs
@@ -38,13 +38,13 @@
 use core::cell::{Cell, UnsafeCell};
 use core::mem::{self, ManuallyDrop};
 use core::num::Wrapping;
-use core::{ptr, fmt};
 use core::sync::atomic;
 use core::sync::atomic::Ordering;
+use core::{fmt, ptr};
 
 use crossbeam_utils::CachePadded;
 
-use atomic::{Shared, Owned};
+use atomic::{Owned, Shared};
 use collector::{Collector, LocalHandle};
 use deferred::Deferred;
 use epoch::{AtomicEpoch, Epoch};
@@ -62,7 +62,7 @@ const MAX_OBJECTS: usize = 4;
 pub struct Bag {
     /// Stashed objects.
     deferreds: [Deferred; MAX_OBJECTS],
-    len: usize
+    len: usize,
 }
 
 /// `Bag::try_push()` requires that it is safe for another thread to execute the given functions.
@@ -104,29 +104,91 @@ impl Bag {
 }
 
 impl Default for Bag {
+    // TODO(taiki-e): when the minimum supported Rust version is bumped to 1.31+,
+    // replace this with `#[rustfmt::skip]`.
+    #[cfg_attr(rustfmt, rustfmt_skip)]
     fn default() -> Self {
         // TODO: [no_op; MAX_OBJECTS] syntax blocked by https://github.com/rust-lang/rust/issues/49147
         #[cfg(not(feature = "sanitize"))]
-        return Bag { len: 0, deferreds:
-            [Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func),
-             Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func)]
+        return Bag {
+            len: 0,
+            deferreds: [
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+            ],
         };
         #[cfg(feature = "sanitize")]
-        return Bag { len: 0, deferreds: [Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func), Deferred::new(no_op_func)] };
+        return Bag {
+            len: 0,
+            deferreds: [
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+                Deferred::new(no_op_func),
+            ],
+        };
     }
 }
 
@@ -144,7 +206,9 @@ impl Drop for Bag {
 // can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long
 impl fmt::Debug for Bag {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("Bag").field("deferreds", &&self.deferreds[..self.len]).finish()
+        f.debug_struct("Bag")
+            .field("deferreds", &&self.deferreds[..self.len])
+            .finish()
     }
 }
 
diff --git a/third_party/rust/crossbeam-epoch/src/lib.rs b/third_party/rust/crossbeam-epoch/src/lib.rs
index c5b504e50c7162ae14d4eb000eb6acd57764e9b2..282bbe90fea016c80fd1653e59958b2349c7bd2b 100644
--- a/third_party/rust/crossbeam-epoch/src/lib.rs
+++ b/third_party/rust/crossbeam-epoch/src/lib.rs
@@ -52,7 +52,7 @@
 //! [`Collector`]: struct.Collector.html
 //! [`Shared`]: struct.Shared.html
 //! [`pin`]: fn.pin.html
-//! [`defer`]: fn.defer.html
+//! [`defer`]: struct.Guard.html#method.defer
 
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
@@ -64,6 +64,8 @@ extern crate cfg_if;
 #[cfg(feature = "std")]
 extern crate core;
 
+extern crate maybe_uninit;
+
 cfg_if! {
     if #[cfg(feature = "alloc")] {
         extern crate alloc;
diff --git a/third_party/rust/crossbeam-epoch/src/sync/list.rs b/third_party/rust/crossbeam-epoch/src/sync/list.rs
index 623fbd2a8efb7215d28e5b87ea88acd031f9db5b..8e8899ea2eb500ef16fb4dd34e85eb48ebf7db48 100644
--- a/third_party/rust/crossbeam-epoch/src/sync/list.rs
+++ b/third_party/rust/crossbeam-epoch/src/sync/list.rs
@@ -243,35 +243,44 @@ impl<'g, T: 'g, C: IsElement<T>> Iterator for Iter<'g, T, C> {
                 // This entry was removed. Try unlinking it from the list.
                 let succ = succ.with_tag(0);
 
-                // The tag should never be zero, because removing a node after a logically deleted
+                // The tag should always be zero, because removing a node after a logically deleted
                 // node leaves the list in an invalid state.
                 debug_assert!(self.curr.tag() == 0);
 
-                match self
+                // Try to unlink `curr` from the list, and get the new value of `self.pred`.
+                let succ = match self
                     .pred
                     .compare_and_set(self.curr, succ, Acquire, self.guard)
                 {
                     Ok(_) => {
-                        // We succeeded in unlinking this element from the list, so we have to
-                        // schedule deallocation. Deferred drop is okay, because `list.delete()`
-                        // can only be called if `T: 'static`.
+                        // We succeeded in unlinking `curr`, so we have to schedule
+                        // deallocation. Deferred drop is okay, because `list.delete()` can only be
+                        // called if `T: 'static`.
                         unsafe {
                             C::finalize(self.curr.deref(), self.guard);
                         }
 
-                        // Move over the removed by only advancing `curr`, not `pred`.
-                        self.curr = succ;
-                        continue;
+                        // `succ` is the new value of `self.pred`.
+                        succ
                     }
-                    Err(_) => {
-                        // A concurrent thread modified the predecessor node. Since it might've
-                        // been deleted, we need to restart from `head`.
-                        self.pred = self.head;
-                        self.curr = self.head.load(Acquire, self.guard);
-
-                        return Some(Err(IterError::Stalled));
+                    Err(e) => {
+                        // `e.current` is the current value of `self.pred`.
+                        e.current
                     }
+                };
+
+                // If the predecessor node is already marked as deleted, we need to restart from
+                // `head`.
+                if succ.tag() != 0 {
+                    self.pred = self.head;
+                    self.curr = self.head.load(Acquire, self.guard);
+
+                    return Some(Err(IterError::Stalled));
                 }
+
+                // Move over the removed by only advancing `curr`, not `pred`.
+                self.curr = succ;
+                continue;
             }
 
             // Move one step forward.
diff --git a/third_party/rust/crossbeam-epoch/src/sync/queue.rs b/third_party/rust/crossbeam-epoch/src/sync/queue.rs
index 6fe0bef37e59b8dd3533f3df41e80682664dea2b..99fb6a1c4f536cc314c42dc435782bec21e924cb 100644
--- a/third_party/rust/crossbeam-epoch/src/sync/queue.rs
+++ b/third_party/rust/crossbeam-epoch/src/sync/queue.rs
@@ -4,13 +4,16 @@
 //!
 //! Michael and Scott.  Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue
 //! Algorithms.  PODC 1996.  http://dl.acm.org/citation.cfm?id=248106
+//!
+//! Simon Doherty, Lindsay Groves, Victor Luchangco, and Mark Moir. 2004b. Formal Verification of a
+//! Practical Lock-Free Queue Algorithm. https://doi.org/10.1007/978-3-540-30232-2_7
 
-use core::mem::{self, ManuallyDrop};
-use core::ptr;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
 
 use crossbeam_utils::CachePadded;
 
+use maybe_uninit::MaybeUninit;
+
 use {unprotected, Atomic, Guard, Owned, Shared};
 
 // The representation here is a singly-linked list, with a sentinel node at the front. In general
@@ -22,15 +25,14 @@ pub struct Queue<T> {
     tail: CachePadded<Atomic<Node<T>>>,
 }
 
-#[derive(Debug)]
 struct Node<T> {
     /// The slot in which a value of type `T` can be stored.
     ///
-    /// The type of `data` is `ManuallyDrop<T>` because a `Node<T>` doesn't always contain a `T`.
+    /// The type of `data` is `MaybeUninit<T>` because a `Node<T>` doesn't always contain a `T`.
     /// For example, the sentinel node in a queue never contains a value: its slot is always empty.
     /// Other nodes start their life with a push operation and contain a value until it gets popped
     /// out. After that such empty nodes get added to the collector for destruction.
-    data: ManuallyDrop<T>,
+    data: MaybeUninit<T>,
 
     next: Atomic<Node<T>>,
 }
@@ -46,11 +48,8 @@ impl<T> Queue<T> {
             head: CachePadded::new(Atomic::null()),
             tail: CachePadded::new(Atomic::null()),
         };
-        // TODO(taiki-e): when the minimum supported Rust version is bumped to 1.36+,
-        // replace this with `mem::MaybeUninit`.
-        #[allow(deprecated)]
         let sentinel = Owned::new(Node {
-            data: unsafe { mem::uninitialized() },
+            data: MaybeUninit::uninit(),
             next: Atomic::null(),
         });
         unsafe {
@@ -90,7 +89,7 @@ impl<T> Queue<T> {
     /// Adds `t` to the back of the queue, possibly waking up threads blocked on `pop`.
     pub fn push(&self, t: T, guard: &Guard) {
         let new = Owned::new(Node {
-            data: ManuallyDrop::new(t),
+            data: MaybeUninit::new(t),
             next: Atomic::null(),
         });
         let new = Owned::into_shared(new, guard);
@@ -117,8 +116,14 @@ impl<T> Queue<T> {
                 self.head
                     .compare_and_set(head, next, Release, guard)
                     .map(|_| {
+                        let tail = self.tail.load(Relaxed, guard);
+                        // Advance the tail so that we don't retire a pointer to a reachable node.
+                        if head == tail {
+                            let _ = self.tail.compare_and_set(tail, next, Release, guard);
+                        }
                         guard.defer_destroy(head);
-                        Some(ManuallyDrop::into_inner(ptr::read(&n.data)))
+                        // TODO: Replace with MaybeUninit::read when api is stable
+                        Some(n.data.as_ptr().read())
                     })
                     .map_err(|_| ())
             },
@@ -138,12 +143,17 @@ impl<T> Queue<T> {
         let h = unsafe { head.deref() };
         let next = h.next.load(Acquire, guard);
         match unsafe { next.as_ref() } {
-            Some(n) if condition(&n.data) => unsafe {
+            Some(n) if condition(unsafe { &*n.data.as_ptr() }) => unsafe {
                 self.head
                     .compare_and_set(head, next, Release, guard)
                     .map(|_| {
+                        let tail = self.tail.load(Relaxed, guard);
+                        // Advance the tail so that we don't retire a pointer to a reachable node.
+                        if head == tail {
+                            let _ = self.tail.compare_and_set(tail, next, Release, guard);
+                        }
                         guard.defer_destroy(head);
-                        Some(ManuallyDrop::into_inner(ptr::read(&n.data)))
+                        Some(n.data.as_ptr().read())
                     })
                     .map_err(|_| ())
             },
diff --git a/third_party/rust/crossbeam-utils-0.6.5/.cargo-checksum.json b/third_party/rust/crossbeam-utils-0.6.5/.cargo-checksum.json
deleted file mode 100644
index ec17be04c27166ca2dbe83cb70a9c2a9667d1fba..0000000000000000000000000000000000000000
--- a/third_party/rust/crossbeam-utils-0.6.5/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"e58bfef23e76d04b244941fd4ecdb35837a1a6f1370bf4596cc0280193c9a4f9","Cargo.toml":"2d4d20231a89e61fa6d1d83ad853b274e71d243c992eda5a9de0c9e8ca428ba5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"63ba61fd2e75aa90572476eda5246fc766846af40d31e0bdccbf763d9f0799ba","benches/atomic_cell.rs":"ada69698def9d4eab485a6e0da235aaac001efe49a6b0d6f5c5be381a645310f","src/atomic/atomic_cell.rs":"97a9ec7ac2625ee0a951b984a419fbeab62173ed9c23cab47dfc13ed25e8ee6c","src/atomic/consume.rs":"bfdc7e2d8370a5a3bb1699b6214347c359d66fcc92a2d1345a513676ac91d821","src/atomic/mod.rs":"404eacae422012f3628cb44262df73a5891fe02a17ab345b832e3062982b5a20","src/backoff.rs":"029fede365eaa3408c7359cf868303120903976304aee546aeedcb80085568d5","src/cache_padded.rs":"95b10657b4e50316d2213894e195c61602ff0c6655cc965301de1584fb7d61c7","src/lib.rs":"957df3bd2875147aa1b939fc47f1a8a72719748e9001f27dba2f3589e27a73b4","src/sync/mod.rs":"4c8ad6ec4601f212791b0b531b46ee5decec2f1d14746aa7f2c18e36c609cd8e","src/sync/parker.rs":"55324bbea5b7c6838a0f8467a5b8a5dbd5526c8e1c7fd4f6d64dad1ab19f9be9","src/sync/sharded_lock.rs":"7a401ba621233732c26cf49324748269359d7bc5dc27e0ec26c9493e9a5ec97d","src/sync/wait_group.rs":"21708bbd46daa98e9f788765a9a4ef3b087a8d1e97a6e9406b4a960c95e44ca0","src/thread.rs":"384e3c6e6db565e752169223205991f1eadb1258b1d416758172a40a6c9bd645","tests/atomic_cell.rs":"690f516c7e827b18adec5da1c3249ebb26ff674c5887d863ddc94fe1600b9c28","tests/cache_padded.rs":"02235757a554279dae5053d46314a765059ec036c63a05336353994c2aa344d1","tests/parker.rs":"996212c084286567638919c27d46a250a5d592d8e1a97c1e6a4d7e10c060e4dd","tests/sharded_lock.rs":"1e2e8a355b74d89569873fbba7772235bc64d13a7209ee673f368f4fe6f70c65","tests/thread.rs":"0d86998085a8aace79e5b3dae61aa8bd864492f44aafcce6ec85778954f55809","tests/wait_group.rs":"e3d5168581fb511b760f4249ca487b919cffc60ac2b4610a78db99899772dd5b"},"package":"f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-utils-0.6.5/LICENSE-MIT b/third_party/rust/crossbeam-utils-0.6.5/LICENSE-MIT
deleted file mode 100644
index 31aa79387f27e730e33d871925e152e35e428031..0000000000000000000000000000000000000000
--- a/third_party/rust/crossbeam-utils-0.6.5/LICENSE-MIT
+++ /dev/null
@@ -1,23 +0,0 @@
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/crossbeam-utils-0.6.6/.cargo-checksum.json b/third_party/rust/crossbeam-utils-0.6.6/.cargo-checksum.json
new file mode 100644
index 0000000000000000000000000000000000000000..b100cb8e15cf100623b5e47b1863c05a3fb4077d
--- /dev/null
+++ b/third_party/rust/crossbeam-utils-0.6.6/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"cb975f0361e0cccfe00da4f32d4c87308b20e40f6444d2ef474640fbb15567de","Cargo.toml":"8ad804e9e161a564e57e2cea30349d9658fd3d32bd0b065868073cdcc70a78cb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"0b293d1b9b129a58f504ff4bc061161ddfaf7c8594e0ca2b526458d4e9acb194","benches/atomic_cell.rs":"fa38d34ddc593bf0999fd65d95ee349c53a11290fbe7bf24870a7e24754ae2ac","src/atomic/atomic_cell.rs":"9f18d8cf7d91750f7646bc2ef7bf5b7444b2c9acdc2e8b6dffd8f0ff696e113b","src/atomic/consume.rs":"bfdc7e2d8370a5a3bb1699b6214347c359d66fcc92a2d1345a513676ac91d821","src/atomic/mod.rs":"404eacae422012f3628cb44262df73a5891fe02a17ab345b832e3062982b5a20","src/backoff.rs":"bc9d2afdd070e0746bc48ff2159bf47b0cfaa68ea09f47eaed18ccc32fc87d67","src/cache_padded.rs":"864f210089eddfd130830f5c700115c2f8b974b71659d7e8ef7bd5e09d7e1f96","src/lib.rs":"3138911610fa97a412c62e4aa5a6cd50524a04f6746c08a5cda8fd1c1d954555","src/sync/mod.rs":"4c8ad6ec4601f212791b0b531b46ee5decec2f1d14746aa7f2c18e36c609cd8e","src/sync/parker.rs":"55324bbea5b7c6838a0f8467a5b8a5dbd5526c8e1c7fd4f6d64dad1ab19f9be9","src/sync/sharded_lock.rs":"7a401ba621233732c26cf49324748269359d7bc5dc27e0ec26c9493e9a5ec97d","src/sync/wait_group.rs":"21708bbd46daa98e9f788765a9a4ef3b087a8d1e97a6e9406b4a960c95e44ca0","src/thread.rs":"ee89256b619c7ed55e04519bb3b9f29e72e6ce1e61e8ba9782a984f5e9fc1bad","tests/atomic_cell.rs":"4423b41f6f23ff2519f4a1f9970436b7fb49968be5bc14dbdbd5ab2d5b1048df","tests/cache_padded.rs":"02235757a554279dae5053d46314a765059ec036c63a05336353994c2aa344d1","tests/parker.rs":"3e5c4e170cebdd9f815f2b31a2b6a01da753fc03e2b1d8e9b899d009f62c6b83","tests/sharded_lock.rs":"3b42218397f1260bed4e0a229f55da83439c0ec9effbbefc86251c9d208979bb","tests/thread.rs":"42baefda11ccd87d9fe1a93bb7d6186b17a86afcf3b9d8f739bc0deefa11ae0f","tests/wait_group.rs":"e3d5168581fb511b760f4249ca487b919cffc60ac2b4610a78db99899772dd5b"},"package":"04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-utils-0.6.5/CHANGELOG.md b/third_party/rust/crossbeam-utils-0.6.6/CHANGELOG.md
similarity index 88%
rename from third_party/rust/crossbeam-utils-0.6.5/CHANGELOG.md
rename to third_party/rust/crossbeam-utils-0.6.6/CHANGELOG.md
index e3a2bdd0727cd0049ce2e67dcf69a969480011a2..6e2102387c35380e5c395d68c4cd2873e2edae67 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/CHANGELOG.md
+++ b/third_party/rust/crossbeam-utils-0.6.6/CHANGELOG.md
@@ -1,3 +1,11 @@
+# Version 0.6.6
+
+- Add `UnwindSafe` and `RefUnwindSafe` impls for `AtomicCell`.
+- Add `AtomicCell::as_ptr()`.
+- Add `AtomicCell::take()`.
+- Fix a bug in `AtomicCell::compare_exchange()` and `AtomicCell::compare_and_swap()`.
+- Various documentation improvements.
+
 # Version 0.6.5
 
 - Rename `Backoff::is_complete()` to `Backoff::is_completed()`.
diff --git a/third_party/rust/crossbeam-utils-0.6.5/Cargo.toml b/third_party/rust/crossbeam-utils-0.6.6/Cargo.toml
similarity index 92%
rename from third_party/rust/crossbeam-utils-0.6.5/Cargo.toml
rename to third_party/rust/crossbeam-utils-0.6.6/Cargo.toml
index 5c2c84b3cd3698fec2e0fae57bb39a2bc70c8ceb..1dbd675ace46c3395c7ddf4ce60a8e903d300fff 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/Cargo.toml
+++ b/third_party/rust/crossbeam-utils-0.6.6/Cargo.toml
@@ -3,7 +3,7 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies
 #
 # If you believe there's an error in this file please file an
 # issue against the rust-lang/cargo repository. If you're
@@ -12,7 +12,7 @@
 
 [package]
 name = "crossbeam-utils"
-version = "0.6.5"
+version = "0.6.6"
 authors = ["The Crossbeam Project Developers"]
 description = "Utilities for concurrent programming"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
@@ -23,7 +23,7 @@ categories = ["algorithms", "concurrency", "data-structures", "no-std"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/crossbeam-rs/crossbeam"
 [dependencies.cfg-if]
-version = "0.1"
+version = "0.1.2"
 
 [dependencies.lazy_static]
 version = "1.1.0"
@@ -32,6 +32,7 @@ optional = true
 version = "0.6"
 
 [features]
+alloc = []
 default = ["std"]
 nightly = []
 std = ["lazy_static"]
diff --git a/third_party/rust/autocfg-0.1.6/LICENSE-APACHE b/third_party/rust/crossbeam-utils-0.6.6/LICENSE-APACHE
similarity index 100%
rename from third_party/rust/autocfg-0.1.6/LICENSE-APACHE
rename to third_party/rust/crossbeam-utils-0.6.6/LICENSE-APACHE
diff --git a/third_party/rust/crossbeam-utils-0.7.0/LICENSE-MIT b/third_party/rust/crossbeam-utils-0.6.6/LICENSE-MIT
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/LICENSE-MIT
rename to third_party/rust/crossbeam-utils-0.6.6/LICENSE-MIT
diff --git a/third_party/rust/crossbeam-utils-0.6.5/README.md b/third_party/rust/crossbeam-utils-0.6.6/README.md
similarity index 85%
rename from third_party/rust/crossbeam-utils-0.6.5/README.md
rename to third_party/rust/crossbeam-utils-0.6.6/README.md
index a454c141ed76a88e5ddd6cef05e3c7b6825a4acb..b4a0f6b20fae5d63ea9d2bf53ce1e9f02185d401 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/README.md
+++ b/third_party/rust/crossbeam-utils-0.6.6/README.md
@@ -10,13 +10,14 @@ https://crates.io/crates/crossbeam-utils)
 https://docs.rs/crossbeam-utils)
 [![Rust 1.26+](https://img.shields.io/badge/rust-1.26+-lightgray.svg)](
 https://www.rust-lang.org)
+[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq)
 
 This crate provides miscellaneous tools for concurrent programming:
 
 #### Atomics
 
-* [`AtomicCell`], a thread-safe mutable memory location.<sup>(\*)</sup>
-* [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.<sup>(\*)</sup>
+* [`AtomicCell`], a thread-safe mutable memory location.<sup>(no_std)</sup>
+* [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.<sup>(no_std)</sup>
 
 #### Thread synchronization
 
@@ -26,11 +27,11 @@ This crate provides miscellaneous tools for concurrent programming:
 
 #### Utilities
 
-* [`Backoff`], for exponential backoff in spin loops.<sup>(\*)</sup>
-* [`CachePadded`], for padding and aligning a value to the length of a cache line.<sup>(\*)</sup>
+* [`Backoff`], for exponential backoff in spin loops.<sup>(no_std)</sup>
+* [`CachePadded`], for padding and aligning a value to the length of a cache line.<sup>(no_std)</sup>
 * [`scope`], for spawning threads that borrow local variables from the stack.
 
-*Features marked with <sup>(\*)</sup> can be used in `no_std` environments.*
+*Features marked with <sup>(no_std)</sup> can be used in `no_std` environments.*<br/>
 
 [`AtomicCell`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/atomic/struct.AtomicCell.html
 [`AtomicConsume`]: https://docs.rs/crossbeam-utils/*/crossbeam_utils/atomic/trait.AtomicConsume.html
diff --git a/third_party/rust/crossbeam-utils-0.7.0/benches/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.6.6/benches/atomic_cell.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/benches/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.6.6/benches/atomic_cell.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/atomic/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.6.6/src/atomic/atomic_cell.rs
similarity index 86%
rename from third_party/rust/crossbeam-utils-0.6.5/src/atomic/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/atomic/atomic_cell.rs
index 31ad7d354ec5a11f91856484a0f9c603b18f3804..f3118ecacf0ed63d0a511225301647455d8980d4 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/src/atomic/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils-0.6.6/src/atomic/atomic_cell.rs
@@ -2,9 +2,11 @@ use core::cell::UnsafeCell;
 use core::fmt;
 use core::mem;
 use core::ptr;
-use core::slice;
 use core::sync::atomic::{self, AtomicBool, AtomicUsize, Ordering};
 
+#[cfg(feature = "std")]
+use std::panic::{RefUnwindSafe, UnwindSafe};
+
 use Backoff;
 
 /// A thread-safe mutable memory location.
@@ -15,9 +17,15 @@ use Backoff;
 /// global locks otherwise. You can call [`AtomicCell::<T>::is_lock_free()`] to check whether
 /// atomic instructions or locks will be used.
 ///
+/// Atomic loads use the [`Acquire`] ordering and atomic stores use the [`Release`] ordering.
+///
 /// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
 /// [`AtomicCell::<T>::is_lock_free()`]: struct.AtomicCell.html#method.is_lock_free
-pub struct AtomicCell<T> {
+/// [`Acquire`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html#variant.Acquire
+/// [`Release`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html#variant.Release
+// TODO(@jeehoonkang): when the minimum supported Rust version is bumped to 1.28+, apply the
+// attribute `#[repr(transparent)]`.
+pub struct AtomicCell<T: ?Sized> {
     /// The inner value.
     ///
     /// If this value can be transmuted into a primitive atomic type, it will be treated as such.
@@ -29,6 +37,11 @@ pub struct AtomicCell<T> {
 unsafe impl<T: Send> Send for AtomicCell<T> {}
 unsafe impl<T: Send> Sync for AtomicCell<T> {}
 
+#[cfg(feature = "std")]
+impl<T> UnwindSafe for AtomicCell<T> {}
+#[cfg(feature = "std")]
+impl<T> RefUnwindSafe for AtomicCell<T> {}
+
 impl<T> AtomicCell<T> {
     /// Creates a new atomic cell initialized with `val`.
     ///
@@ -45,22 +58,6 @@ impl<T> AtomicCell<T> {
         }
     }
 
-    /// Returns a mutable reference to the inner value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use crossbeam_utils::atomic::AtomicCell;
-    ///
-    /// let mut a = AtomicCell::new(7);
-    /// *a.get_mut() += 1;
-    ///
-    /// assert_eq!(a.load(), 8);
-    /// ```
-    pub fn get_mut(&mut self) -> &mut T {
-        unsafe { &mut *self.value.get() }
-    }
-
     /// Unwraps the atomic cell and returns its inner value.
     ///
     /// # Examples
@@ -150,6 +147,61 @@ impl<T> AtomicCell<T> {
     }
 }
 
+impl<T: ?Sized> AtomicCell<T> {
+    /// Returns a raw pointer to the underlying data in this atomic cell.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let mut a = AtomicCell::new(5);
+    ///
+    /// let ptr = a.as_ptr();
+    /// ```
+    #[inline]
+    pub fn as_ptr(&self) -> *mut T {
+        self.value.get()
+    }
+
+    /// Returns a mutable reference to the inner value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let mut a = AtomicCell::new(7);
+    /// *a.get_mut() += 1;
+    ///
+    /// assert_eq!(a.load(), 8);
+    /// ```
+    #[doc(hidden)]
+    #[deprecated(note = "this method is unsound and will be removed in the next release")]
+    pub fn get_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.value.get() }
+    }
+}
+
+impl<T: Default> AtomicCell<T> {
+    /// Takes the value of the atomic cell, leaving `Default::default()` in its place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let a = AtomicCell::new(5);
+    /// let five = a.take();
+    ///
+    /// assert_eq!(five, 5);
+    /// assert_eq!(a.into_inner(), 0);
+    /// ```
+    pub fn take(&self) -> T {
+        self.swap(Default::default())
+    }
+}
+
 impl<T: Copy> AtomicCell<T> {
     /// Loads a value.
     ///
@@ -180,10 +232,10 @@ impl<T: Copy + Eq> AtomicCell<T> {
     ///
     /// let a = AtomicCell::new(1);
     ///
-    /// assert_eq!(a.compare_exchange(2, 3), Err(1));
+    /// assert_eq!(a.compare_and_swap(2, 3), 1);
     /// assert_eq!(a.load(), 1);
     ///
-    /// assert_eq!(a.compare_exchange(1, 2), Ok(1));
+    /// assert_eq!(a.compare_and_swap(1, 2), 1);
     /// assert_eq!(a.load(), 2);
     /// ```
     pub fn compare_and_swap(&self, current: T, new: T) -> T {
@@ -211,23 +263,8 @@ impl<T: Copy + Eq> AtomicCell<T> {
     /// assert_eq!(a.compare_exchange(1, 2), Ok(1));
     /// assert_eq!(a.load(), 2);
     /// ```
-    pub fn compare_exchange(&self, mut current: T, new: T) -> Result<T, T> {
-        loop {
-            match unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) } {
-                Ok(_) => return Ok(current),
-                Err(previous) => {
-                    if previous != current {
-                        return Err(previous);
-                    }
-
-                    // The compare-exchange operation has failed and didn't store `new`. The
-                    // failure is either spurious, or `previous` was semantically equal to
-                    // `current` but not byte-equal. Let's retry with `previous` as the new
-                    // `current`.
-                    current = previous;
-                }
-            }
-        }
+    pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
+        unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) }
     }
 }
 
@@ -252,7 +289,7 @@ macro_rules! impl_arithmetic {
             pub fn fetch_add(&self, val: $t) -> $t {
                 if can_transmute::<$t, atomic::AtomicUsize>() {
                     let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_add(val as usize, Ordering::SeqCst) as $t
+                    a.fetch_add(val as usize, Ordering::AcqRel) as $t
                 } else {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
@@ -280,7 +317,7 @@ macro_rules! impl_arithmetic {
             pub fn fetch_sub(&self, val: $t) -> $t {
                 if can_transmute::<$t, atomic::AtomicUsize>() {
                     let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_sub(val as usize, Ordering::SeqCst) as $t
+                    a.fetch_sub(val as usize, Ordering::AcqRel) as $t
                 } else {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
@@ -306,7 +343,7 @@ macro_rules! impl_arithmetic {
             pub fn fetch_and(&self, val: $t) -> $t {
                 if can_transmute::<$t, atomic::AtomicUsize>() {
                     let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_and(val as usize, Ordering::SeqCst) as $t
+                    a.fetch_and(val as usize, Ordering::AcqRel) as $t
                 } else {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
@@ -332,7 +369,7 @@ macro_rules! impl_arithmetic {
             pub fn fetch_or(&self, val: $t) -> $t {
                 if can_transmute::<$t, atomic::AtomicUsize>() {
                     let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_or(val as usize, Ordering::SeqCst) as $t
+                    a.fetch_or(val as usize, Ordering::AcqRel) as $t
                 } else {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
@@ -358,7 +395,7 @@ macro_rules! impl_arithmetic {
             pub fn fetch_xor(&self, val: $t) -> $t {
                 if can_transmute::<$t, atomic::AtomicUsize>() {
                     let a = unsafe { &*(self.value.get() as *const atomic::AtomicUsize) };
-                    a.fetch_xor(val as usize, Ordering::SeqCst) as $t
+                    a.fetch_xor(val as usize, Ordering::AcqRel) as $t
                 } else {
                     let _guard = lock(self.value.get() as usize).write();
                     let value = unsafe { &mut *(self.value.get()) };
@@ -388,7 +425,7 @@ macro_rules! impl_arithmetic {
             #[inline]
             pub fn fetch_add(&self, val: $t) -> $t {
                 let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_add(val, Ordering::SeqCst)
+                a.fetch_add(val, Ordering::AcqRel)
             }
 
             /// Decrements the current value by `val` and returns the previous value.
@@ -408,7 +445,7 @@ macro_rules! impl_arithmetic {
             #[inline]
             pub fn fetch_sub(&self, val: $t) -> $t {
                 let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_sub(val, Ordering::SeqCst)
+                a.fetch_sub(val, Ordering::AcqRel)
             }
 
             /// Applies bitwise "and" to the current value and returns the previous value.
@@ -426,7 +463,7 @@ macro_rules! impl_arithmetic {
             #[inline]
             pub fn fetch_and(&self, val: $t) -> $t {
                 let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_and(val, Ordering::SeqCst)
+                a.fetch_and(val, Ordering::AcqRel)
             }
 
             /// Applies bitwise "or" to the current value and returns the previous value.
@@ -444,7 +481,7 @@ macro_rules! impl_arithmetic {
             #[inline]
             pub fn fetch_or(&self, val: $t) -> $t {
                 let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_or(val, Ordering::SeqCst)
+                a.fetch_or(val, Ordering::AcqRel)
             }
 
             /// Applies bitwise "xor" to the current value and returns the previous value.
@@ -462,7 +499,7 @@ macro_rules! impl_arithmetic {
             #[inline]
             pub fn fetch_xor(&self, val: $t) -> $t {
                 let a = unsafe { &*(self.value.get() as *const $atomic) };
-                a.fetch_xor(val, Ordering::SeqCst)
+                a.fetch_xor(val, Ordering::AcqRel)
             }
         }
     };
@@ -528,7 +565,7 @@ impl AtomicCell<bool> {
     #[inline]
     pub fn fetch_and(&self, val: bool) -> bool {
         let a = unsafe { &*(self.value.get() as *const AtomicBool) };
-        a.fetch_and(val, Ordering::SeqCst)
+        a.fetch_and(val, Ordering::AcqRel)
     }
 
     /// Applies logical "or" to the current value and returns the previous value.
@@ -549,7 +586,7 @@ impl AtomicCell<bool> {
     #[inline]
     pub fn fetch_or(&self, val: bool) -> bool {
         let a = unsafe { &*(self.value.get() as *const AtomicBool) };
-        a.fetch_or(val, Ordering::SeqCst)
+        a.fetch_or(val, Ordering::AcqRel)
     }
 
     /// Applies logical "xor" to the current value and returns the previous value.
@@ -570,7 +607,7 @@ impl AtomicCell<bool> {
     #[inline]
     pub fn fetch_xor(&self, val: bool) -> bool {
         let a = unsafe { &*(self.value.get() as *const AtomicBool) };
-        a.fetch_xor(val, Ordering::SeqCst)
+        a.fetch_xor(val, Ordering::AcqRel)
     }
 }
 
@@ -588,15 +625,6 @@ impl<T: Copy + fmt::Debug> fmt::Debug for AtomicCell<T> {
     }
 }
 
-/// Returns `true` if the two values are equal byte-for-byte.
-fn byte_eq<T>(a: &T, b: &T) -> bool {
-    unsafe {
-        let a = slice::from_raw_parts(a as *const _ as *const u8, mem::size_of::<T>());
-        let b = slice::from_raw_parts(b as *const _ as *const u8, mem::size_of::<T>());
-        a == b
-    }
-}
-
 /// Returns `true` if values of type `A` can be transmuted into values of type `B`.
 fn can_transmute<A, B>() -> bool {
     // Sizes must be equal, but alignment of `A` must be greater or equal than that of `B`.
@@ -803,7 +831,7 @@ fn atomic_is_lock_free<T>() -> bool {
 
 /// Atomically reads data from `src`.
 ///
-/// This operation uses the `SeqCst` ordering. If possible, an atomic instructions is used, and a
+/// This operation uses the `Acquire` ordering. If possible, an atomic instructions is used, and a
 /// global lock otherwise.
 unsafe fn atomic_load<T>(src: *mut T) -> T
 where
@@ -813,7 +841,7 @@ where
         T, a,
         {
             a = &*(src as *const _ as *const _);
-            mem::transmute_copy(&a.load(Ordering::SeqCst))
+            mem::transmute_copy(&a.load(Ordering::Acquire))
         },
         {
             let lock = lock(src as usize);
@@ -844,34 +872,33 @@ where
 
 /// Atomically writes `val` to `dst`.
 ///
-/// This operation uses the `SeqCst` ordering. If possible, an atomic instructions is used, and a
+/// This operation uses the `Release` ordering. If possible, an atomic instructions is used, and a
 /// global lock otherwise.
 unsafe fn atomic_store<T>(dst: *mut T, val: T) {
     atomic! {
         T, a,
         {
             a = &*(dst as *const _ as *const _);
-            let res = a.store(mem::transmute_copy(&val), Ordering::SeqCst);
+            a.store(mem::transmute_copy(&val), Ordering::Release);
             mem::forget(val);
-            res
         },
         {
             let _guard = lock(dst as usize).write();
-            ptr::write(dst, val)
+            ptr::write(dst, val);
         }
     }
 }
 
 /// Atomically swaps data at `dst` with `val`.
 ///
-/// This operation uses the `SeqCst` ordering. If possible, an atomic instructions is used, and a
+/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a
 /// global lock otherwise.
 unsafe fn atomic_swap<T>(dst: *mut T, val: T) -> T {
     atomic! {
         T, a,
         {
             a = &*(dst as *const _ as *const _);
-            let res = mem::transmute_copy(&a.swap(mem::transmute_copy(&val), Ordering::SeqCst));
+            let res = mem::transmute_copy(&a.swap(mem::transmute_copy(&val), Ordering::AcqRel));
             mem::forget(val);
             res
         },
@@ -887,31 +914,48 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T) -> T {
 ///
 /// Returns the old value on success, or the current value at `dst` on failure.
 ///
-/// This operation uses the `SeqCst` ordering. If possible, an atomic instructions is used, and a
+/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a
 /// global lock otherwise.
-unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T, current: T, new: T) -> Result<T, T>
+unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T, mut current: T, new: T) -> Result<T, T>
 where
-    T: Copy,
+    T: Copy + Eq,
 {
     atomic! {
         T, a,
         {
             a = &*(dst as *const _ as *const _);
-            let res = a.compare_exchange_weak(
-                mem::transmute_copy(&current),
-                mem::transmute_copy(&new),
-                Ordering::SeqCst,
-                Ordering::SeqCst,
-            );
-            match res {
-                Ok(v) => Ok(mem::transmute_copy(&v)),
-                Err(v) => Err(mem::transmute_copy(&v)),
+            let mut current_raw = mem::transmute_copy(&current);
+            let new_raw = mem::transmute_copy(&new);
+
+            loop {
+                match a.compare_exchange_weak(
+                    current_raw,
+                    new_raw,
+                    Ordering::AcqRel,
+                    Ordering::Acquire,
+                ) {
+                    Ok(_) => break Ok(current),
+                    Err(previous_raw) => {
+                        let previous = mem::transmute_copy(&previous_raw);
+
+                        if !T::eq(&previous, &current) {
+                            break Err(previous);
+                        }
+
+                        // The compare-exchange operation has failed and didn't store `new`. The
+                        // failure is either spurious, or `previous` was semantically equal to
+                        // `current` but not byte-equal. Let's retry with `previous` as the new
+                        // `current`.
+                        current = previous;
+                        current_raw = previous_raw;
+                    }
+                }
             }
         },
         {
             let guard = lock(dst as usize).write();
 
-            if byte_eq(&*dst, &current) {
+            if T::eq(&*dst, &current) {
                 Ok(ptr::replace(dst, new))
             } else {
                 let val = ptr::read(dst);
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/atomic/consume.rs b/third_party/rust/crossbeam-utils-0.6.6/src/atomic/consume.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/atomic/consume.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/atomic/consume.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/atomic/mod.rs b/third_party/rust/crossbeam-utils-0.6.6/src/atomic/mod.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/atomic/mod.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/atomic/mod.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/backoff.rs b/third_party/rust/crossbeam-utils-0.6.6/src/backoff.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/backoff.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/backoff.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/cache_padded.rs b/third_party/rust/crossbeam-utils-0.6.6/src/cache_padded.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/cache_padded.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/cache_padded.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/lib.rs b/third_party/rust/crossbeam-utils-0.6.6/src/lib.rs
similarity index 88%
rename from third_party/rust/crossbeam-utils-0.6.5/src/lib.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/lib.rs
index 82b49aa5bf2e50852a4d2f1f92179d509dafdd6d..4df2ac8a455c83eeab11c2ce2fca902fbd3bbaff 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/src/lib.rs
+++ b/third_party/rust/crossbeam-utils-0.6.6/src/lib.rs
@@ -29,7 +29,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "nightly", feature(alloc))]
 #![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
 
 #[macro_use]
@@ -38,16 +37,17 @@ extern crate cfg_if;
 extern crate core;
 
 cfg_if! {
-    if #[cfg(feature = "nightly")] {
+    if #[cfg(feature = "alloc")] {
         extern crate alloc;
-    } else {
-        mod alloc {
-            extern crate std;
-            pub use self::std::*;
-        }
+    } else if #[cfg(feature = "std")] {
+        extern crate std as alloc;
     }
 }
 
+#[cfg_attr(
+    feature = "nightly",
+    cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
+)]
 pub mod atomic;
 
 mod cache_padded;
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/sync/mod.rs b/third_party/rust/crossbeam-utils-0.6.6/src/sync/mod.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/sync/mod.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/sync/mod.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/sync/parker.rs b/third_party/rust/crossbeam-utils-0.6.6/src/sync/parker.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/sync/parker.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/sync/parker.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/sync/sharded_lock.rs b/third_party/rust/crossbeam-utils-0.6.6/src/sync/sharded_lock.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/sync/sharded_lock.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/sync/sharded_lock.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/sync/wait_group.rs b/third_party/rust/crossbeam-utils-0.6.6/src/sync/wait_group.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/src/sync/wait_group.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/sync/wait_group.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/thread.rs b/third_party/rust/crossbeam-utils-0.6.6/src/thread.rs
similarity index 99%
rename from third_party/rust/crossbeam-utils-0.6.5/src/thread.rs
rename to third_party/rust/crossbeam-utils-0.6.6/src/thread.rs
index 495e9b1ca8130d221251ccd6bd19a72fcfd07308..2613fb7855a9c358eecb18e657986c500347e430 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/src/thread.rs
+++ b/third_party/rust/crossbeam-utils-0.6.6/src/thread.rs
@@ -74,7 +74,7 @@
 //! `'static` lifetime because the borrow checker cannot be sure when the thread will complete.
 //!
 //! A scope creates a clear boundary between variables outside the scope and threads inside the
-//! scope. Whenever a s.spawns a thread, it promises to join the thread before the scope ends.
+//! scope. Whenever a scope spawns a thread, it promises to join the thread before the scope ends.
 //! This way we guarantee to the borrow checker that scoped threads only live within the scope and
 //! can safely access variables outside it.
 //!
@@ -92,14 +92,14 @@
 //!         // Not going to compile because we're trying to borrow `s`,
 //!         // which lives *inside* the scope! :(
 //!         s.spawn(|_| println!("nested thread"));
-//!     }});
+//!     });
 //! });
 //! ```
 //!
 //! Fortunately, there is a solution. Every scoped thread is passed a reference to its scope as an
 //! argument, which can be used for spawning nested threads:
 //!
-//! ```ignore
+//! ```
 //! use crossbeam_utils::thread;
 //!
 //! thread::scope(|s| {
@@ -107,7 +107,7 @@
 //!     s.spawn(|s| {
 //!         // Yay, this works because we're using a fresh argument `s`! :)
 //!         s.spawn(|_| println!("nested thread"));
-//!     }});
+//!     });
 //! });
 //! ```
 //!
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/atomic_cell.rs
similarity index 96%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/atomic_cell.rs
index 57206aeda1edb7bbfedaa8425c4d08a3bf5f84e7..940619233340d775fcd4e17b1fee328bd991f029 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/tests/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils-0.6.6/tests/atomic_cell.rs
@@ -223,12 +223,3 @@ fn garbage_padding() {
     assert!(cell.compare_exchange(prev, next).is_ok());
     println!();
 }
-
-#[cfg(has_min_const_fn)]
-#[test]
-fn const_atomic_cell_new() {
-    static CELL: AtomicCell<usize> = AtomicCell::new(0);
-
-    CELL.store(1);
-    assert_eq!(CELL.load(), 1);
-}
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/cache_padded.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/cache_padded.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/cache_padded.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/cache_padded.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/parker.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/parker.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/parker.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/parker.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/sharded_lock.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/sharded_lock.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/sharded_lock.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/sharded_lock.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/thread.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/thread.rs
similarity index 96%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/thread.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/thread.rs
index ac7c2b2a78db04a42fe87da5b412caacf7cddc4d..b691745e0b85ef63fa2bac7449f49bc045cb5180 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/tests/thread.rs
+++ b/third_party/rust/crossbeam-utils-0.6.6/tests/thread.rs
@@ -23,7 +23,8 @@ fn join() {
             panic!("\"My honey is running out!\", said Pooh.");
         });
         assert!(panic_handle.join().is_err());
-    }).unwrap();
+    })
+    .unwrap();
 
     // There should be sufficient synchronization.
     assert_eq!(1, counter.load(Ordering::Relaxed));
@@ -38,7 +39,8 @@ fn counter() {
                 counter.fetch_add(1, Ordering::Relaxed);
             });
         }
-    }).unwrap();
+    })
+    .unwrap();
 
     assert_eq!(THREADS, counter.load(Ordering::Relaxed));
 }
@@ -54,9 +56,11 @@ fn counter_builder() {
                 .stack_size(SMALL_STACK_SIZE)
                 .spawn(|_| {
                     counter.fetch_add(1, Ordering::Relaxed);
-                }).unwrap();
+                })
+                .unwrap();
         }
-    }).unwrap();
+    })
+    .unwrap();
 
     assert_eq!(THREADS, counter.load(Ordering::Relaxed));
 }
@@ -157,7 +161,8 @@ fn nesting() {
                 wrapper.recurse(scope, 5);
             });
         });
-    }).unwrap();
+    })
+    .unwrap();
 }
 
 #[test]
@@ -171,5 +176,6 @@ fn join_nested() {
         });
 
         sleep(Duration::from_millis(100));
-    }).unwrap();
+    })
+    .unwrap();
 }
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/wait_group.rs b/third_party/rust/crossbeam-utils-0.6.6/tests/wait_group.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/wait_group.rs
rename to third_party/rust/crossbeam-utils-0.6.6/tests/wait_group.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/LICENSE-APACHE b/third_party/rust/crossbeam-utils-0.7.0/LICENSE-APACHE
deleted file mode 100644
index 16fe87b06e802f094b3fbb0894b137bca2b16ef1..0000000000000000000000000000000000000000
--- a/third_party/rust/crossbeam-utils-0.7.0/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/third_party/rust/crossbeam-utils-0.7.0/build.rs b/third_party/rust/crossbeam-utils-0.7.0/build.rs
deleted file mode 100644
index d451c24b2f1fa64f283c026693f838f7aabbc7e3..0000000000000000000000000000000000000000
--- a/third_party/rust/crossbeam-utils-0.7.0/build.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-extern crate autocfg;
-
-fn main() {
-    let cfg = autocfg::new();
-    if cfg.probe_rustc_version(1, 31) {
-        println!("cargo:rustc-cfg=has_min_const_fn");
-    }
-}
diff --git a/third_party/rust/crossbeam-utils-0.7.0/.cargo-checksum.json b/third_party/rust/crossbeam-utils-0.7.2/.cargo-checksum.json
similarity index 51%
rename from third_party/rust/crossbeam-utils-0.7.0/.cargo-checksum.json
rename to third_party/rust/crossbeam-utils-0.7.2/.cargo-checksum.json
index 330718f051e462b76313a7b66ce93f761515592a..47f9d2b5e748cc4574e5761d19681ebb1c4d74d3 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/.cargo-checksum.json
+++ b/third_party/rust/crossbeam-utils-0.7.2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"c728a651e916eeb36060274c25cf28817920caf498eb5a367fecdaebe3139f5b","Cargo.toml":"d72c5990059398ec7a203d13a4fc8c5dd7e1c051199415d33475675acb377f9a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"9010e511423b1159a33c84433d9e6cb8df1d08938e4d6cc8656bcec9bdde0eb8","benches/atomic_cell.rs":"fa38d34ddc593bf0999fd65d95ee349c53a11290fbe7bf24870a7e24754ae2ac","build.rs":"825c47ae19028dc4b28101ec71c04e7e41b8b185f6ecbeacee223596524c86ad","src/atomic/atomic_cell.rs":"609adf6aa30d8685c1f708887a17c19f90f8751400b83d8146d078afb5a31c48","src/atomic/consume.rs":"bfdc7e2d8370a5a3bb1699b6214347c359d66fcc92a2d1345a513676ac91d821","src/atomic/mod.rs":"6c3efec60aee6a2e68dfa6fe3c059beab8429c150459ce5cfc736e8b5f95301e","src/atomic/seq_lock.rs":"4797f76beb0ec3eb363c2d49e9548adc8d042867b1602c1b8ca6269463d84e82","src/atomic/seq_lock_wide.rs":"d27243fae36ae9ff72cbf24defcac4abb2aef3fa11a47f352702708a1eee6a06","src/backoff.rs":"bc9d2afdd070e0746bc48ff2159bf47b0cfaa68ea09f47eaed18ccc32fc87d67","src/cache_padded.rs":"864f210089eddfd130830f5c700115c2f8b974b71659d7e8ef7bd5e09d7e1f96","src/lib.rs":"63096ede0c6ccdee05e910c2cce41da6df283868b658f9aa18c8fba8ac0f901d","src/sync/mod.rs":"4c8ad6ec4601f212791b0b531b46ee5decec2f1d14746aa7f2c18e36c609cd8e","src/sync/parker.rs":"55324bbea5b7c6838a0f8467a5b8a5dbd5526c8e1c7fd4f6d64dad1ab19f9be9","src/sync/sharded_lock.rs":"7a401ba621233732c26cf49324748269359d7bc5dc27e0ec26c9493e9a5ec97d","src/sync/wait_group.rs":"21708bbd46daa98e9f788765a9a4ef3b087a8d1e97a6e9406b4a960c95e44ca0","src/thread.rs":"81f6ee718c5251083024583d351a1713cb6a850c284f68e5fa8a35d2ed4b33ba","tests/atomic_cell.rs":"a3c9e7d5832c92fa7e39710a3dc84b4a906eb93479386fba75ff851dd1c908ae","tests/cache_padded.rs":"02235757a554279dae5053d46314a765059ec036c63a05336353994c2aa344d1","tests/parker.rs":"3e5c4e170cebdd9f815f2b31a2b6a01da753fc03e2b1d8e9b899d009f62c6b83","tests/sharded_lock.rs":"3b42218397f1260bed4e0a229f55da83439c0ec9effbbefc86251c9d208979bb","tests/thread.rs":"4be7b293b5f13d7a158a231ba7f7b086bd8fe19aaf11b1c9a8a6cdf7bba6fdfc","tests/wait_group.rs":"e3d5168581fb511b760f4249ca487b919cffc60ac2b4610a78db99899772dd5b"},"package":"ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"ed7fb11c83cc30f6e7af6a42cae2cb087276ba1668da98268c86fccf9069baa7","Cargo.toml":"3c1187fa9a66336c9c959c87c6ad499f6a6adabb6a10506abaf6ed53e02d57cb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"9010e511423b1159a33c84433d9e6cb8df1d08938e4d6cc8656bcec9bdde0eb8","benches/atomic_cell.rs":"fa38d34ddc593bf0999fd65d95ee349c53a11290fbe7bf24870a7e24754ae2ac","build.rs":"1ceb20e3c4e089a4dbf326df7924643be0bd6d50512b0b0a0729dbb30522eba8","src/atomic/atomic_cell.rs":"49b8a014e7009292c1eb3b241c2120a661bffcc40bf7b9de83dbb6928b5315b4","src/atomic/consume.rs":"bfdc7e2d8370a5a3bb1699b6214347c359d66fcc92a2d1345a513676ac91d821","src/atomic/mod.rs":"6c3efec60aee6a2e68dfa6fe3c059beab8429c150459ce5cfc736e8b5f95301e","src/atomic/seq_lock.rs":"4797f76beb0ec3eb363c2d49e9548adc8d042867b1602c1b8ca6269463d84e82","src/atomic/seq_lock_wide.rs":"4b2eb90599fbf548e79b8da5e2533d6f7c133245ae8dd48353ef52b1d2aa17f0","src/backoff.rs":"bc9d2afdd070e0746bc48ff2159bf47b0cfaa68ea09f47eaed18ccc32fc87d67","src/cache_padded.rs":"864f210089eddfd130830f5c700115c2f8b974b71659d7e8ef7bd5e09d7e1f96","src/lib.rs":"63096ede0c6ccdee05e910c2cce41da6df283868b658f9aa18c8fba8ac0f901d","src/sync/mod.rs":"02a7cc2a5ebb988a86aeebf7a40752f595e5eb494750e63cdbefd71c4643e2a3","src/sync/parker.rs":"442d8814339fdd9d7074e7e00695c64e6bbb62a2b0c1c8c1e0f4a471c25ccbbd","src/sync/sharded_lock.rs":"756a27476cbbdb03629a18d5b82c6153f7f168d8ef28f0fa17daf103affcc013","src/sync/wait_group.rs":"319611cfba289e272d38bdc9624ce110e37db5ffa2644d23dc330edc153850f0","src/thread.rs":"81f6ee718c5251083024583d351a1713cb6a850c284f68e5fa8a35d2ed4b33ba","tests/atomic_cell.rs":"945885f96d6a5971d6bfbd27ec8da79d337558373a631ffe2c83c6851da360e7","tests/cache_padded.rs":"02235757a554279dae5053d46314a765059ec036c63a05336353994c2aa344d1","tests/parker.rs":"3e5c4e170cebdd9f815f2b31a2b6a01da753fc03e2b1d8e9b899d009f62c6b83","tests/sharded_lock.rs":"3b42218397f1260bed4e0a229f55da83439c0ec9effbbefc86251c9d208979bb","tests/thread.rs":"4be7b293b5f13d7a158a231ba7f7b086bd8fe19aaf11b1c9a8a6cdf7bba6fdfc","tests/wait_group.rs":"e3d5168581fb511b760f4249ca487b919cffc60ac2b4610a78db99899772dd5b"},"package":"c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-utils-0.7.0/CHANGELOG.md b/third_party/rust/crossbeam-utils-0.7.2/CHANGELOG.md
similarity index 92%
rename from third_party/rust/crossbeam-utils-0.7.0/CHANGELOG.md
rename to third_party/rust/crossbeam-utils-0.7.2/CHANGELOG.md
index 160e92888157d981f855e6f12fafbd3b7d9d9a64..d5fee12d1f70ea82b8f4ec56bd62b84366263f8c 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/CHANGELOG.md
+++ b/third_party/rust/crossbeam-utils-0.7.2/CHANGELOG.md
@@ -1,3 +1,12 @@
+# Version 0.7.2
+
+- Fix bug in release (yanking 0.7.1)
+
+# Version 0.7.1
+
+- Bump `autocfg` dependency to version 1.0. (#460)
+- Make `AtomicCell` lockfree for u8, u16, u32, u64 sized values at 1.34+. (#454)
+
 # Version 0.7.0
 
 - Bump the minimum required version to 1.28.
diff --git a/third_party/rust/crossbeam-utils-0.7.0/Cargo.toml b/third_party/rust/crossbeam-utils-0.7.2/Cargo.toml
similarity index 97%
rename from third_party/rust/crossbeam-utils-0.7.0/Cargo.toml
rename to third_party/rust/crossbeam-utils-0.7.2/Cargo.toml
index c16268bf6ec0609b0da1d4bb0a52bc4e1eaf6ba6..372e06fd0bd7a3ed73c81795340055dc3cc65105 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/Cargo.toml
+++ b/third_party/rust/crossbeam-utils-0.7.2/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "crossbeam-utils"
-version = "0.7.0"
+version = "0.7.2"
 authors = ["The Crossbeam Project Developers"]
 description = "Utilities for concurrent programming"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
@@ -31,7 +31,7 @@ optional = true
 [dev-dependencies.rand]
 version = "0.6"
 [build-dependencies.autocfg]
-version = "0.1.6"
+version = "1"
 
 [features]
 alloc = []
diff --git a/third_party/rust/crossbeam-utils-0.6.5/LICENSE-APACHE b/third_party/rust/crossbeam-utils-0.7.2/LICENSE-APACHE
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.6.5/LICENSE-APACHE
rename to third_party/rust/crossbeam-utils-0.7.2/LICENSE-APACHE
diff --git a/third_party/rust/autocfg-0.1.6/LICENSE-MIT b/third_party/rust/crossbeam-utils-0.7.2/LICENSE-MIT
similarity index 93%
rename from third_party/rust/autocfg-0.1.6/LICENSE-MIT
rename to third_party/rust/crossbeam-utils-0.7.2/LICENSE-MIT
index 44fbc4d8b90dbe07864fdf49939308839e5735b2..068d491fd551ae2531f4d28583245719a2e19e2d 100644
--- a/third_party/rust/autocfg-0.1.6/LICENSE-MIT
+++ b/third_party/rust/crossbeam-utils-0.7.2/LICENSE-MIT
@@ -1,4 +1,6 @@
-Copyright (c) 2018 Josh Stone
+The MIT License (MIT)
+
+Copyright (c) 2019 The Crossbeam Project Developers
 
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
diff --git a/third_party/rust/crossbeam-utils-0.7.0/README.md b/third_party/rust/crossbeam-utils-0.7.2/README.md
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/README.md
rename to third_party/rust/crossbeam-utils-0.7.2/README.md
diff --git a/third_party/rust/crossbeam-utils-0.6.5/benches/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.7.2/benches/atomic_cell.rs
similarity index 75%
rename from third_party/rust/crossbeam-utils-0.6.5/benches/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.7.2/benches/atomic_cell.rs
index aae17d41192a93708fb07821b57012407a957dbf..8587dba1d9f4a4c792c423a3dce377d75fa9e402 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/benches/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/benches/atomic_cell.rs
@@ -51,20 +51,18 @@ fn concurrent_load_u8(b: &mut test::Bencher) {
 
     thread::scope(|scope| {
         for _ in 0..THREADS {
-            scope.spawn(|_| {
-                loop {
-                    start.wait();
-
-                    let mut sum = 0;
-                    for _ in 0..STEPS {
-                        sum += a.load();
-                    }
-                    test::black_box(sum);
-
-                    end.wait();
-                    if exit.load() {
-                        break;
-                    }
+            scope.spawn(|_| loop {
+                start.wait();
+
+                let mut sum = 0;
+                for _ in 0..STEPS {
+                    sum += a.load();
+                }
+                test::black_box(sum);
+
+                end.wait();
+                if exit.load() {
+                    break;
                 }
             });
         }
@@ -80,7 +78,8 @@ fn concurrent_load_u8(b: &mut test::Bencher) {
         start.wait();
         exit.store(true);
         end.wait();
-    }).unwrap();
+    })
+    .unwrap();
 }
 
 #[bench]
@@ -126,20 +125,18 @@ fn concurrent_load_usize(b: &mut test::Bencher) {
 
     thread::scope(|scope| {
         for _ in 0..THREADS {
-            scope.spawn(|_| {
-                loop {
-                    start.wait();
-
-                    let mut sum = 0;
-                    for _ in 0..STEPS {
-                        sum += a.load();
-                    }
-                    test::black_box(sum);
-
-                    end.wait();
-                    if exit.load() {
-                        break;
-                    }
+            scope.spawn(|_| loop {
+                start.wait();
+
+                let mut sum = 0;
+                for _ in 0..STEPS {
+                    sum += a.load();
+                }
+                test::black_box(sum);
+
+                end.wait();
+                if exit.load() {
+                    break;
                 }
             });
         }
@@ -155,5 +152,6 @@ fn concurrent_load_usize(b: &mut test::Bencher) {
         start.wait();
         exit.store(true);
         end.wait();
-    }).unwrap();
+    })
+    .unwrap();
 }
diff --git a/third_party/rust/crossbeam-utils-0.7.2/build.rs b/third_party/rust/crossbeam-utils-0.7.2/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2f5012ad763a3879de94b0ffd7d0a9aa277b770d
--- /dev/null
+++ b/third_party/rust/crossbeam-utils-0.7.2/build.rs
@@ -0,0 +1,14 @@
+extern crate autocfg;
+
+fn main() {
+    let cfg = autocfg::new();
+    if cfg.probe_rustc_version(1, 31) {
+        autocfg::emit("has_min_const_fn");
+    }
+
+    cfg.emit_type_cfg("core::sync::atomic::AtomicU8", "has_atomic_u8");
+    cfg.emit_type_cfg("core::sync::atomic::AtomicU16", "has_atomic_u16");
+    cfg.emit_type_cfg("core::sync::atomic::AtomicU32", "has_atomic_u32");
+    cfg.emit_type_cfg("core::sync::atomic::AtomicU64", "has_atomic_u64");
+    cfg.emit_type_cfg("core::sync::atomic::AtomicU128", "has_atomic_u128");
+}
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/atomic_cell.rs
similarity index 92%
rename from third_party/rust/crossbeam-utils-0.7.0/src/atomic/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/atomic/atomic_cell.rs
index 76aae65f8a83f5654c1ef2ee12cf895e9c197795..cf0658aad4582949db6e92fd85fe4082ad61670a 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/atomic_cell.rs
@@ -519,37 +519,28 @@ macro_rules! impl_arithmetic {
             }
         }
     };
-    ($t:ty, $size:tt, $atomic:ty, $example:tt) => {
-        #[cfg(target_has_atomic = $size)]
-        impl_arithmetic!($t, $atomic, $example);
-    };
 }
 
-cfg_if! {
-    if #[cfg(feature = "nightly")] {
-        impl_arithmetic!(u8, "8", atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
-        impl_arithmetic!(i8, "8", atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
-        impl_arithmetic!(u16, "16", atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
-        impl_arithmetic!(i16, "16", atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
-        impl_arithmetic!(u32, "32", atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
-        impl_arithmetic!(i32, "32", atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
-        impl_arithmetic!(u64, "64", atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-        impl_arithmetic!(i64, "64", atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
-        impl_arithmetic!(u128, "let a = AtomicCell::new(7u128);");
-        impl_arithmetic!(i128, "let a = AtomicCell::new(7i128);");
-    } else {
-        impl_arithmetic!(u8, "let a = AtomicCell::new(7u8);");
-        impl_arithmetic!(i8, "let a = AtomicCell::new(7i8);");
-        impl_arithmetic!(u16, "let a = AtomicCell::new(7u16);");
-        impl_arithmetic!(i16, "let a = AtomicCell::new(7i16);");
-        impl_arithmetic!(u32, "let a = AtomicCell::new(7u32);");
-        impl_arithmetic!(i32, "let a = AtomicCell::new(7i32);");
-        impl_arithmetic!(u64, "let a = AtomicCell::new(7u64);");
-        impl_arithmetic!(i64, "let a = AtomicCell::new(7i64);");
-        impl_arithmetic!(u128, "let a = AtomicCell::new(7u128);");
-        impl_arithmetic!(i128, "let a = AtomicCell::new(7i128);");
-    }
-}
+#[cfg(has_atomic_u8)]
+impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
+#[cfg(has_atomic_u8)]
+impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
+#[cfg(has_atomic_u16)]
+impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
+#[cfg(has_atomic_u16)]
+impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
+#[cfg(has_atomic_u32)]
+impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
+#[cfg(has_atomic_u32)]
+impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
+#[cfg(has_atomic_u64)]
+impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
+#[cfg(has_atomic_u64)]
+impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
+#[cfg(has_atomic_u128)]
+impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
+#[cfg(has_atomic_u128)]
+impl_arithmetic!(i128, atomic::AtomicI128, "let  a = AtomicCell::new(7i128);");
 
 impl_arithmetic!(
     usize,
@@ -741,17 +732,14 @@ macro_rules! atomic {
             atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
             atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
 
-            #[cfg(feature = "nightly")]
-            {
-                #[cfg(target_has_atomic = "8")]
-                atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
-                #[cfg(target_has_atomic = "16")]
-                atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
-                #[cfg(target_has_atomic = "32")]
-                atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
-                #[cfg(target_has_atomic = "64")]
-                atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
-            }
+            #[cfg(has_atomic_u8)]
+            atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
+            #[cfg(has_atomic_u16)]
+            atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
+            #[cfg(has_atomic_u32)]
+            atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
+            #[cfg(has_atomic_u64)]
+            atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
 
             break $fallback_op;
         }
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/consume.rs b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/consume.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/atomic/consume.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/atomic/consume.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/mod.rs b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/mod.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/atomic/mod.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/atomic/mod.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/seq_lock.rs b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/seq_lock.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/atomic/seq_lock.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/atomic/seq_lock.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/seq_lock_wide.rs b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/seq_lock_wide.rs
similarity index 97%
rename from third_party/rust/crossbeam-utils-0.7.0/src/atomic/seq_lock_wide.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/atomic/seq_lock_wide.rs
index 090a849bd88c16a8a29706de44fcbbcafcd3b6bc..857c074f59d5a25f9a01a0f20ed40e8f835b36b7 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/atomic/seq_lock_wide.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/atomic/seq_lock_wide.rs
@@ -121,7 +121,9 @@ impl Drop for SeqLockWriteGuard {
         // Release ordering for synchronizing with `optimistic_read`.
         if state_lo == 0 {
             let state_hi = self.lock.state_hi.load(Ordering::Relaxed);
-            self.lock.state_hi.store(state_hi.wrapping_add(1), Ordering::Release);
+            self.lock
+                .state_hi
+                .store(state_hi.wrapping_add(1), Ordering::Release);
         }
 
         // Release the lock and increment the stamp.
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/backoff.rs b/third_party/rust/crossbeam-utils-0.7.2/src/backoff.rs
similarity index 99%
rename from third_party/rust/crossbeam-utils-0.6.5/src/backoff.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/backoff.rs
index 49619917b1a2336b2a035702c847d2dfd95397a2..446755bbc7b4841ac8847cfee49cef8ff2de7894 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/src/backoff.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/backoff.rs
@@ -93,9 +93,7 @@ impl Backoff {
     /// ```
     #[inline]
     pub fn new() -> Self {
-        Backoff {
-            step: Cell::new(0),
-        }
+        Backoff { step: Cell::new(0) }
     }
 
     /// Resets the `Backoff`.
diff --git a/third_party/rust/crossbeam-utils-0.6.5/src/cache_padded.rs b/third_party/rust/crossbeam-utils-0.7.2/src/cache_padded.rs
similarity index 64%
rename from third_party/rust/crossbeam-utils-0.6.5/src/cache_padded.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/cache_padded.rs
index a5f3bbc1ccd235fa61a00006b56f074efccb90cf..bb864a419121d7507675a4ab7bee06d4d62b7393 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/src/cache_padded.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/cache_padded.rs
@@ -9,14 +9,22 @@ use core::ops::{Deref, DerefMut};
 /// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other
 /// cached data.
 ///
-/// Cache lines are assumed to be 64 bytes on all architectures.
-///
 /// # Size and alignment
 ///
-/// The size of `CachePadded<T>` is the smallest multiple of 64 bytes large enough to accommodate
+/// Cache lines are assumed to be N bytes long, depending on the architecture:
+///
+/// * On x86-64, N = 128.
+/// * On all others, N = 64.
+///
+/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
+/// length of the machine the program is running on. On modern Intel architectures, spatial
+/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that
+/// cache lines are 128 bytes long.
+///
+/// The size of `CachePadded<T>` is the smallest multiple of N bytes large enough to accommodate
 /// a value of type `T`.
 ///
-/// The alignment of `CachePadded<T>` is the maximum of 64 bytes and the alignment of `T`.
+/// The alignment of `CachePadded<T>` is the maximum of N bytes and the alignment of `T`.
 ///
 /// # Examples
 ///
@@ -25,11 +33,11 @@ use core::ops::{Deref, DerefMut};
 /// ```
 /// use crossbeam_utils::CachePadded;
 ///
-/// let array = [CachePadded::new(1i32), CachePadded::new(2i32)];
-/// let addr1 = &*array[0] as *const i32 as usize;
-/// let addr2 = &*array[1] as *const i32 as usize;
+/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)];
+/// let addr1 = &*array[0] as *const i8 as usize;
+/// let addr2 = &*array[1] as *const i8 as usize;
 ///
-/// assert_eq!(addr2 - addr1, 64);
+/// assert!(addr2 - addr1 >= 64);
 /// assert_eq!(addr1 % 64, 0);
 /// assert_eq!(addr2 % 64, 0);
 /// ```
@@ -49,7 +57,14 @@ use core::ops::{Deref, DerefMut};
 /// }
 /// ```
 #[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
-#[repr(align(64))]
+// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache
+// lines at a time, so we have to align to 128 bytes rather than 64.
+//
+// Sources:
+// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
+// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
+#[cfg_attr(target_arch = "x86_64", repr(align(128)))]
+#[cfg_attr(not(target_arch = "x86_64"), repr(align(64)))]
 pub struct CachePadded<T> {
     value: T,
 }
@@ -71,7 +86,7 @@ impl<T> CachePadded<T> {
         CachePadded::<T> { value: t }
     }
 
-    /// Returns the value value.
+    /// Returns the inner value.
     ///
     /// # Examples
     ///
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/lib.rs b/third_party/rust/crossbeam-utils-0.7.2/src/lib.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/lib.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/lib.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/sync/mod.rs b/third_party/rust/crossbeam-utils-0.7.2/src/sync/mod.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/sync/mod.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/sync/mod.rs
index 31c8ffec4dfb8f8391954523b1bdebd87b1625e0..3634963725f8c0c9de945f698a4652f599c01ca8 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/sync/mod.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/sync/mod.rs
@@ -12,6 +12,6 @@ mod parker;
 mod sharded_lock;
 mod wait_group;
 
-pub use self::sharded_lock::{ShardedLock, ShardedLockReadGuard, ShardedLockWriteGuard};
 pub use self::parker::{Parker, Unparker};
+pub use self::sharded_lock::{ShardedLock, ShardedLockReadGuard, ShardedLockWriteGuard};
 pub use self::wait_group::WaitGroup;
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/sync/parker.rs b/third_party/rust/crossbeam-utils-0.7.2/src/sync/parker.rs
similarity index 96%
rename from third_party/rust/crossbeam-utils-0.7.0/src/sync/parker.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/sync/parker.rs
index 506db8e39318a473b9eb8a4bd63194c2fa69a536..051afe512da82ebd3fcca664ea0f648752d4ec4d 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/sync/parker.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/sync/parker.rs
@@ -1,8 +1,8 @@
 use std::fmt;
 use std::marker::PhantomData;
-use std::sync::{Arc, Condvar, Mutex};
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
+use std::sync::{Arc, Condvar, Mutex};
 use std::time::Duration;
 
 /// A thread parking primitive.
@@ -228,7 +228,11 @@ struct Inner {
 impl Inner {
     fn park(&self, timeout: Option<Duration>) {
         // If we were previously notified then we consume this notification and return quickly.
-        if self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst).is_ok() {
+        if self
+            .state
+            .compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst)
+            .is_ok()
+        {
             return;
         }
 
@@ -266,7 +270,7 @@ impl Inner {
 
                     match self.state.compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst) {
                         Ok(_) => return, // got a notification
-                        Err(_) => {} // spurious wakeup, go back to sleep
+                        Err(_) => {}     // spurious wakeup, go back to sleep
                     }
                 }
             }
@@ -278,7 +282,7 @@ impl Inner {
 
                 match self.state.swap(EMPTY, SeqCst) {
                     NOTIFIED => {} // got a notification
-                    PARKED => {} // no notification
+                    PARKED => {}   // no notification
                     n => panic!("inconsistent park_timeout state: {}", n),
                 }
             }
@@ -291,9 +295,9 @@ impl Inner {
         // `NOTIFIED` even if `state` is already `NOTIFIED`. That is why this must be a swap rather
         // than a compare-and-swap that returns if it reads `NOTIFIED` on failure.
         match self.state.swap(NOTIFIED, SeqCst) {
-            EMPTY => return, // no one was waiting
+            EMPTY => return,    // no one was waiting
             NOTIFIED => return, // already unparked
-            PARKED => {} // gotta go wake someone up
+            PARKED => {}        // gotta go wake someone up
             _ => panic!("inconsistent state in unpark"),
         }
 
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/sync/sharded_lock.rs b/third_party/rust/crossbeam-utils-0.7.2/src/sync/sharded_lock.rs
similarity index 96%
rename from third_party/rust/crossbeam-utils-0.7.0/src/sync/sharded_lock.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/sync/sharded_lock.rs
index 0fbb29175fd5deafbace49353658475de50f7237..bd269d1584c5e72bbb06b0898216676475d5bec8 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/sync/sharded_lock.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/sync/sharded_lock.rs
@@ -5,8 +5,8 @@ use std::marker::PhantomData;
 use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::panic::{RefUnwindSafe, UnwindSafe};
-use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
 use std::sync::{LockResult, PoisonError, TryLockError, TryLockResult};
+use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
 use std::thread::{self, ThreadId};
 
 use CachePadded;
@@ -99,10 +99,12 @@ impl<T> ShardedLock<T> {
     pub fn new(value: T) -> ShardedLock<T> {
         ShardedLock {
             shards: (0..NUM_SHARDS)
-                .map(|_| CachePadded::new(Shard {
-                    lock: RwLock::new(()),
-                    write_guard: UnsafeCell::new(None),
-                }))
+                .map(|_| {
+                    CachePadded::new(Shard {
+                        lock: RwLock::new(()),
+                        write_guard: UnsafeCell::new(None),
+                    })
+                })
                 .collect::<Vec<_>>()
                 .into_boxed_slice(),
             value: UnsafeCell::new(value),
@@ -232,7 +234,7 @@ impl<T: ?Sized> ShardedLock<T> {
                     _marker: PhantomData,
                 };
                 Err(TryLockError::Poisoned(PoisonError::new(guard)))
-            },
+            }
             Err(TryLockError::WouldBlock) => Err(TryLockError::WouldBlock),
         }
     }
@@ -317,7 +319,7 @@ impl<T: ?Sized> ShardedLock<T> {
                 Err(TryLockError::Poisoned(err)) => {
                     poisoned = true;
                     err.into_inner()
-                },
+                }
                 Err(TryLockError::WouldBlock) => {
                     blocked = Some(i);
                     break;
@@ -416,10 +418,14 @@ impl<T: ?Sized> ShardedLock<T> {
 impl<T: ?Sized + fmt::Debug> fmt::Debug for ShardedLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_read() {
-            Ok(guard) => f.debug_struct("ShardedLock").field("data", &&*guard).finish(),
-            Err(TryLockError::Poisoned(err)) => {
-                f.debug_struct("ShardedLock").field("data", &&**err.get_ref()).finish()
-            },
+            Ok(guard) => f
+                .debug_struct("ShardedLock")
+                .field("data", &&*guard)
+                .finish(),
+            Err(TryLockError::Poisoned(err)) => f
+                .debug_struct("ShardedLock")
+                .field("data", &&**err.get_ref())
+                .finish(),
             Err(TryLockError::WouldBlock) => {
                 struct LockedPlaceholder;
                 impl fmt::Debug for LockedPlaceholder {
@@ -427,7 +433,9 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for ShardedLock<T> {
                         f.write_str("<locked>")
                     }
                 }
-                f.debug_struct("ShardedLock").field("data", &LockedPlaceholder).finish()
+                f.debug_struct("ShardedLock")
+                    .field("data", &LockedPlaceholder)
+                    .finish()
             }
         }
     }
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/sync/wait_group.rs b/third_party/rust/crossbeam-utils-0.7.2/src/sync/wait_group.rs
similarity index 97%
rename from third_party/rust/crossbeam-utils-0.7.0/src/sync/wait_group.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/sync/wait_group.rs
index 16ddc3091c03f88543e5e71d13a159336ff15acd..0527b31593d5d442783d1bb67274d8b78db26d28 100644
--- a/third_party/rust/crossbeam-utils-0.7.0/src/sync/wait_group.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/src/sync/wait_group.rs
@@ -132,8 +132,6 @@ impl Clone for WaitGroup {
 impl fmt::Debug for WaitGroup {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let count: &usize = &*self.inner.count.lock().unwrap();
-        f.debug_struct("WaitGroup")
-            .field("count", count)
-            .finish()
+        f.debug_struct("WaitGroup").field("count", count).finish()
     }
 }
diff --git a/third_party/rust/crossbeam-utils-0.7.0/src/thread.rs b/third_party/rust/crossbeam-utils-0.7.2/src/thread.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/src/thread.rs
rename to third_party/rust/crossbeam-utils-0.7.2/src/thread.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/atomic_cell.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/atomic_cell.rs
similarity index 81%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/atomic_cell.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/atomic_cell.rs
index 37c901f04288da4019ff2845312609d7e95f6485..e0b7db525b652ebd847aeae7f199b5536d8abbe2 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/tests/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/tests/atomic_cell.rs
@@ -9,20 +9,19 @@ use crossbeam_utils::atomic::AtomicCell;
 fn is_lock_free() {
     struct UsizeWrap(usize);
     struct U8Wrap(bool);
+    struct I16Wrap(i16);
 
     assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
     assert_eq!(AtomicCell::<isize>::is_lock_free(), true);
     assert_eq!(AtomicCell::<UsizeWrap>::is_lock_free(), true);
 
-    assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(feature = "nightly"));
-    assert_eq!(
-        AtomicCell::<bool>::is_lock_free(),
-        cfg!(feature = "nightly")
-    );
-    assert_eq!(
-        AtomicCell::<U8Wrap>::is_lock_free(),
-        cfg!(feature = "nightly")
-    );
+    assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(has_atomic_u8));
+    assert_eq!(AtomicCell::<bool>::is_lock_free(), cfg!(has_atomic_u8));
+    assert_eq!(AtomicCell::<U8Wrap>::is_lock_free(), cfg!(has_atomic_u8));
+
+    assert_eq!(AtomicCell::<I16Wrap>::is_lock_free(), cfg!(has_atomic_u16));
+
+    assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
 }
 
 #[test]
@@ -206,3 +205,29 @@ fn modular_usize() {
     assert_eq!(a.compare_exchange(Foo(10), Foo(15)), Ok(Foo(100)));
     assert_eq!(a.load().0, 15);
 }
+
+#[test]
+fn garbage_padding() {
+    #[derive(Copy, Clone, Eq, PartialEq)]
+    struct Object {
+        a: i64,
+        b: i32,
+    }
+
+    let cell = AtomicCell::new(Object { a: 0, b: 0 });
+    let _garbage = [0xfe, 0xfe, 0xfe, 0xfe, 0xfe]; // Needed
+    let next = Object { a: 0, b: 0 };
+
+    let prev = cell.load();
+    assert!(cell.compare_exchange(prev, next).is_ok());
+    println!();
+}
+
+#[cfg(has_min_const_fn)]
+#[test]
+fn const_atomic_cell_new() {
+    static CELL: AtomicCell<usize> = AtomicCell::new(0);
+
+    CELL.store(1);
+    assert_eq!(CELL.load(), 1);
+}
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/cache_padded.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/cache_padded.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/cache_padded.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/cache_padded.rs
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/parker.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/parker.rs
similarity index 96%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/parker.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/parker.rs
index fab07b3a3c7a944c5cd8d3dab55e945898e4a972..3f4514626a2a235dabcc02ab4d9fa22c9f7686b9 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/tests/parker.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/tests/parker.rs
@@ -37,6 +37,7 @@ fn park_timeout_unpark_called_other_thread() {
             });
 
             p.park_timeout(Duration::from_millis(u32::MAX as u64));
-        }).unwrap();
+        })
+        .unwrap();
     }
 }
diff --git a/third_party/rust/crossbeam-utils-0.6.5/tests/sharded_lock.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/sharded_lock.rs
similarity index 95%
rename from third_party/rust/crossbeam-utils-0.6.5/tests/sharded_lock.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/sharded_lock.rs
index 374c3c36cc8e76ac5a6db6c6f73f0121a0b55f3e..c98de799983923c8d305214580cc8f1f7b306b46 100644
--- a/third_party/rust/crossbeam-utils-0.6.5/tests/sharded_lock.rs
+++ b/third_party/rust/crossbeam-utils-0.7.2/tests/sharded_lock.rs
@@ -1,10 +1,10 @@
 extern crate crossbeam_utils;
 extern crate rand;
 
+use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::mpsc::channel;
-use std::thread;
 use std::sync::{Arc, TryLockError};
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::thread;
 
 use crossbeam_utils::sync::ShardedLock;
 use rand::Rng;
@@ -55,7 +55,8 @@ fn arc_poison_wr() {
     let _: Result<(), _> = thread::spawn(move || {
         let _lock = arc2.write().unwrap();
         panic!();
-    }).join();
+    })
+    .join();
     assert!(arc.read().is_err());
 }
 
@@ -67,7 +68,8 @@ fn arc_poison_ww() {
     let _: Result<(), _> = thread::spawn(move || {
         let _lock = arc2.write().unwrap();
         panic!();
-    }).join();
+    })
+    .join();
     assert!(arc.write().is_err());
     assert!(arc.is_poisoned());
 }
@@ -79,7 +81,8 @@ fn arc_no_poison_rr() {
     let _: Result<(), _> = thread::spawn(move || {
         let _lock = arc2.read().unwrap();
         panic!();
-    }).join();
+    })
+    .join();
     let lock = arc.read().unwrap();
     assert_eq!(*lock, 1);
 }
@@ -90,7 +93,8 @@ fn arc_no_poison_sl() {
     let _: Result<(), _> = thread::spawn(move || {
         let _lock = arc2.read().unwrap();
         panic!()
-    }).join();
+    })
+    .join();
     let lock = arc.write().unwrap();
     assert_eq!(*lock, 1);
 }
@@ -149,7 +153,8 @@ fn arc_access_in_unwind() {
         }
         let _u = Unwinder { i: arc2 };
         panic!();
-    }).join();
+    })
+    .join();
     let lock = arc.read().unwrap();
     assert_eq!(*lock, 2);
 }
@@ -174,7 +179,10 @@ fn try_write() {
     let write_result = lock.try_write();
     match write_result {
         Err(TryLockError::WouldBlock) => (),
-        Ok(_) => assert!(false, "try_write should not succeed while read_guard is in scope"),
+        Ok(_) => assert!(
+            false,
+            "try_write should not succeed while read_guard is in scope"
+        ),
         Err(_) => assert!(false, "unexpected error"),
     }
 
@@ -212,7 +220,8 @@ fn test_into_inner_poison() {
     let _ = thread::spawn(move || {
         let _lock = m2.write().unwrap();
         panic!("test panic in inner thread to poison ShardedLock");
-    }).join();
+    })
+    .join();
 
     assert!(m.is_poisoned());
     match Arc::try_unwrap(m).unwrap().into_inner() {
@@ -235,7 +244,8 @@ fn test_get_mut_poison() {
     let _ = thread::spawn(move || {
         let _lock = m2.write().unwrap();
         panic!("test panic in inner thread to poison ShardedLock");
-    }).join();
+    })
+    .join();
 
     assert!(m.is_poisoned());
     match Arc::try_unwrap(m).unwrap().get_mut() {
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/thread.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/thread.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/thread.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/thread.rs
diff --git a/third_party/rust/crossbeam-utils-0.7.0/tests/wait_group.rs b/third_party/rust/crossbeam-utils-0.7.2/tests/wait_group.rs
similarity index 100%
rename from third_party/rust/crossbeam-utils-0.7.0/tests/wait_group.rs
rename to third_party/rust/crossbeam-utils-0.7.2/tests/wait_group.rs
diff --git a/third_party/rust/crossbeam-utils/.cargo-checksum.json b/third_party/rust/crossbeam-utils/.cargo-checksum.json
index 9a264617eedb56bf367c8c5fcdd0279d7863ae06..4ffc417110012eef096e595607e1fea92feb1450 100644
--- a/third_party/rust/crossbeam-utils/.cargo-checksum.json
+++ b/third_party/rust/crossbeam-utils/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"36557d1a612004b5108ed46be3716bb2e06368d5bb0cd9e7ea4b6bcc4d81c07a","Cargo.toml":"648a34c3609f0cb729929fd5c6d1288475232a4daeb79363e629ecadcc5d3a4f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"5bbcf23ea854d44870790a316dbcdb8d7b0c2e0f17a521e8d4fbffdd9dd5b464","benches/atomic_cell.rs":"de327015cf811fb74b7a624719f678ba0677025dc703d56cbd2094a3c92da23b","build.rs":"f927f9796b0cbae832f458e82833b24c7ced9f27f4f1e76de9d11ad30d21c88a","src/atomic/atomic_cell.rs":"4b86367084da93176c335650524220ef7b3df4df09b6535d0b55a03446dee7e0","src/atomic/consume.rs":"1ee5de160b6e3755c02940c24fa90f85f3ef2f7afb971e9e9c6f481609bbc7b7","src/atomic/mod.rs":"c84d068944388c1385d6fec9211b6be26c777a21fc04e7231d1f3b564de62708","src/atomic/seq_lock.rs":"ee50097cd582cfe6e28ebc54935fc6488f52e2fed19d4b26bafd5eab5c229291","src/atomic/seq_lock_wide.rs":"f03ee779c2ebebcfb0df8baac49be7d38e920876260c8da9dff0fc894068c35d","src/backoff.rs":"98d1daee75bbd6243bc0784c92c56086e57658baff93a2a1f0729426901c03ee","src/cache_padded.rs":"5671f3a02f6e407f1dc562d4fb17e4659f18d1e5206b8566b38d2e447e5f6fa4","src/lib.rs":"61c6bc2b43d87550c4547693f3eacfe126581560a8884b32b23f01a7e2c6d833","src/sync/mod.rs":"e5f4087c4e63b0e6e0b291f3946a224aa9d2a4a0c299c23014b822d6346f6986","src/sync/parker.rs":"6137fccce8c03045440cbc3166721e4e4b5f73013165c9c260cff904cfcab6f3","src/sync/sharded_lock.rs":"14be659744918d0b27db24c56b41c618b0f0484b6761da46561023d96c4c120f","src/sync/wait_group.rs":"932e11753764b238f764892978a6b70fb288111faf7fae7766e603bed4e5b444","src/thread.rs":"6c44bf4c4515a769b8ccd0c9d9b80f5b46bd4768ec323a909773301d375033fb","tests/atomic_cell.rs":"5efe71777d7687ee01e387d5ca20436c3e8171e1e879a63074d1f79ccc88ff5e","tests/cache_padded.rs":"6ba6ad1b3060bfb2f7bf0a1d006f949d91c49e506564b0d28e4f06129b94665d","tests/parker.rs":"a1f63cf99b3524bfc91d0797133d0b75165445ecbaa92f78bd8101fa7cc828ec","tests/sharded_lock.rs":"c7d9f7185900b3ff84d00f5252793d5d28c47374678b8e6f758a67fa32c71fca","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"ad8f0cdfed31f9594a2e0737234d418f8b924d784a4db8d7e469deab8c95f5f8"},"package":"02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"5242f1740c65509c465c9a36326d344722facff5f5e58dd064f7b77806b83a46","Cargo.toml":"ac35a7b8ccb16f1ab256951576537aa4179a316c068929c2acef89e0adc12319","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"dfa9fbed47c344c134a63c84b7c0e4651baeac1554b7b3266d0e38643743fc33","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build.rs":"68cfc4be02429834a19411fba29cb1cb52c841f03ac8104d1bae59a8b2184f9c","no_atomic.rs":"a2621c1b029c614fb0ab8e3f5cda2e839df88d90d26133181c1b901965f7eec4","src/atomic/atomic_cell.rs":"1a3a1e073340317b5ce7a94e29c6a87db89ff7e00da6b92cb3c0339364c3b084","src/atomic/consume.rs":"7a7736fcd64f6473dfea7653559ffc5e1a2a234df43835f8aa8734862145ac15","src/atomic/mod.rs":"7f6afd5bd0da1f7b51765ab04da4e5f683588ac2d23506e61bf7007bb1e61ba2","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"7cc7754e15f69b52e92a70d4f49d1bc274693455a0933a2d7eb0605806566af3","src/cache_padded.rs":"6a512698115ad0d5a5b163dbd7a83247e1f1c146c4a30f3fc74b952e3b767b59","src/lib.rs":"6f1bcf157abe06ad8458a53e865bf8efab9fad4a9424790147cee8fefb3795d8","src/sync/mod.rs":"59986f559a8f170a4b3247ab2eea2460b09809d87c8110ed88e4e7103d3519dc","src/sync/parker.rs":"ba8f75bff31b8be9275808e8f393e71cc682dfc1109ceccb12f69a3700cff5be","src/sync/sharded_lock.rs":"14be659744918d0b27db24c56b41c618b0f0484b6761da46561023d96c4c120f","src/sync/wait_group.rs":"32e946a7581c55f8aa9904527b92b177c538fa0cf7cbcfa1d1f25990582cb6ea","src/thread.rs":"0eb5ec1d3c1b40600d88eb70539d14276e32307f5bed2b679f50f6a20777a01e","tests/atomic_cell.rs":"6c9453384ecbbe76f8b97b62f022d478d3a76b4eae1e960f49790970f5d52158","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"726025ce6351fb56ed629d5a56bdf6e833b7afc5dedfa08de0b056c726b6c26d","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"ad8f0cdfed31f9594a2e0737234d418f8b924d784a4db8d7e469deab8c95f5f8"},"package":"d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"}
\ No newline at end of file
diff --git a/third_party/rust/crossbeam-utils/CHANGELOG.md b/third_party/rust/crossbeam-utils/CHANGELOG.md
index a17c6e6f15d57c983e53095e65284a568345438f..8c485ef6b1a07a0b4f0ea4c6d3ac0adada8fb2f9 100644
--- a/third_party/rust/crossbeam-utils/CHANGELOG.md
+++ b/third_party/rust/crossbeam-utils/CHANGELOG.md
@@ -1,3 +1,23 @@
+# Version 0.8.5
+
+- Add `AtomicCell::fetch_update` (#704)
+- Support targets that do not have atomic CAS on stable Rust (#698)
+
+# Version 0.8.4
+
+- Bump `loom` dependency to version 0.5. (#686)
+
+# Version 0.8.3
+
+- Make `loom` dependency optional. (#666)
+
+# Version 0.8.2
+
+- Deprecate `AtomicCell::compare_and_swap`. Use `AtomicCell::compare_exchange` instead. (#619)
+- Add `Parker::park_deadline`. (#563)
+- Improve implementation of `CachePadded`. (#636)
+- Add unstable support for `loom`. (#487)
+
 # Version 0.8.1
 
 - Make `AtomicCell::is_lock_free` always const fn. (#600)
@@ -8,7 +28,7 @@
 # Version 0.8.0
 
 - Bump the minimum supported Rust version to 1.36.
-- Remove deprecated `AtomicCell::get_mut()` and `Backoff::is_complete()` methods
+- Remove deprecated `AtomicCell::get_mut()` and `Backoff::is_complete()` methods.
 - Remove `alloc` feature.
 - Make `CachePadded::new()` const function.
 - Make `AtomicCell::is_lock_free()` const function at 1.46+.
diff --git a/third_party/rust/crossbeam-utils/Cargo.toml b/third_party/rust/crossbeam-utils/Cargo.toml
index edb08f9998e1923fae56c15d0b0ea45efc0d3ea6..0b32b467165ec7ef31f44c2fe7454ccda3f13567 100644
--- a/third_party/rust/crossbeam-utils/Cargo.toml
+++ b/third_party/rust/crossbeam-utils/Cargo.toml
@@ -13,12 +13,11 @@
 [package]
 edition = "2018"
 name = "crossbeam-utils"
-version = "0.8.1"
+version = "0.8.5"
 authors = ["The Crossbeam Project Developers"]
 description = "Utilities for concurrent programming"
 homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
 documentation = "https://docs.rs/crossbeam-utils"
-readme = "README.md"
 keywords = ["scoped", "thread", "atomic", "cache"]
 categories = ["algorithms", "concurrency", "data-structures", "no-std"]
 license = "MIT OR Apache-2.0"
@@ -30,11 +29,12 @@ version = "1"
 version = "1.4.0"
 optional = true
 [dev-dependencies.rand]
-version = "0.7.3"
-[build-dependencies.autocfg]
-version = "1.0.0"
+version = "0.8"
 
 [features]
 default = ["std"]
 nightly = []
 std = ["lazy_static"]
+[target."cfg(crossbeam_loom)".dependencies.loom]
+version = "0.5"
+optional = true
diff --git a/third_party/rust/crossbeam-utils/README.md b/third_party/rust/crossbeam-utils/README.md
index 7e95829874e7f0ed958b3b45317b8897454b2af6..6e9a8e49a51a50a274e20321b0336d91abbe70ed 100644
--- a/third_party/rust/crossbeam-utils/README.md
+++ b/third_party/rust/crossbeam-utils/README.md
@@ -2,7 +2,7 @@
 
 [![Build Status](https://github.com/crossbeam-rs/crossbeam/workflows/CI/badge.svg)](
 https://github.com/crossbeam-rs/crossbeam/actions)
-[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](
+[![License](https://img.shields.io/badge/license-MIT_OR_Apache--2.0-blue.svg)](
 https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils#license)
 [![Cargo](https://img.shields.io/crates/v/crossbeam-utils.svg)](
 https://crates.io/crates/crossbeam-utils)
@@ -10,7 +10,7 @@ https://crates.io/crates/crossbeam-utils)
 https://docs.rs/crossbeam-utils)
 [![Rust 1.36+](https://img.shields.io/badge/rust-1.36+-lightgray.svg)](
 https://www.rust-lang.org)
-[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.gg/BBYwKq)
+[![chat](https://img.shields.io/discord/569610676205781012.svg?logo=discord)](https://discord.com/invite/JXYwgWZ)
 
 This crate provides miscellaneous tools for concurrent programming:
 
diff --git a/third_party/rust/crossbeam-utils/benches/atomic_cell.rs b/third_party/rust/crossbeam-utils/benches/atomic_cell.rs
index 938a8fe3809802324a44617d6e708002454ee24d..844f7c02b63e1f370319a07e305ff2dfa593950b 100644
--- a/third_party/rust/crossbeam-utils/benches/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils/benches/atomic_cell.rs
@@ -28,11 +28,11 @@ fn fetch_add_u8(b: &mut test::Bencher) {
 }
 
 #[bench]
-fn compare_and_swap_u8(b: &mut test::Bencher) {
+fn compare_exchange_u8(b: &mut test::Bencher) {
     let a = AtomicCell::new(0u8);
     let mut i = 0;
     b.iter(|| {
-        a.compare_and_swap(i, i.wrapping_add(1));
+        let _ = a.compare_exchange(i, i.wrapping_add(1));
         i = i.wrapping_add(1);
     });
 }
@@ -102,11 +102,11 @@ fn fetch_add_usize(b: &mut test::Bencher) {
 }
 
 #[bench]
-fn compare_and_swap_usize(b: &mut test::Bencher) {
+fn compare_exchange_usize(b: &mut test::Bencher) {
     let a = AtomicCell::new(0usize);
     let mut i = 0;
     b.iter(|| {
-        a.compare_and_swap(i, i.wrapping_add(1));
+        let _ = a.compare_exchange(i, i.wrapping_add(1));
         i = i.wrapping_add(1);
     });
 }
diff --git a/third_party/rust/crossbeam-utils/build.rs b/third_party/rust/crossbeam-utils/build.rs
index 3e51021835a074e26d6c58b9a58080f8829fa312..9c924adeb734583879832e161e712e8b3df008ce 100644
--- a/third_party/rust/crossbeam-utils/build.rs
+++ b/third_party/rust/crossbeam-utils/build.rs
@@ -1,23 +1,40 @@
-use autocfg::AutoCfg;
+#![warn(rust_2018_idioms)]
+
+use std::env;
+
+include!("no_atomic.rs");
 
 // The rustc-cfg strings below are *not* public API. Please let us know by
 // opening a GitHub issue if your build environment requires some way to enable
 // these cfgs other than by executing our build script.
 fn main() {
-    let cfg = match AutoCfg::new() {
-        Ok(cfg) => cfg,
+    let target = match env::var("TARGET") {
+        Ok(target) => target,
         Err(e) => {
             println!(
-                "cargo:warning=crossbeam-utils: unable to determine rustc version: {}",
+                "cargo:warning={}: unable to get TARGET environment variable: {}",
+                env!("CARGO_PKG_NAME"),
                 e
             );
             return;
         }
     };
 
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU8", "has_atomic_u8");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU16", "has_atomic_u16");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU32", "has_atomic_u32");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU64", "has_atomic_u64");
-    cfg.emit_type_cfg("core::sync::atomic::AtomicU128", "has_atomic_u128");
+    // Note that this is `no_*`, not `has_*`. This allows treating
+    // `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
+    // run. This is needed for compatibility with non-cargo build systems that
+    // don't run the build script.
+    if NO_ATOMIC_CAS.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_cas");
+    }
+    if NO_ATOMIC.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic");
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+    } else if NO_ATOMIC_64.contains(&&*target) {
+        println!("cargo:rustc-cfg=crossbeam_no_atomic_64");
+    } else {
+        // Otherwise, assuming `"max-atomic-width" == 64`.
+    }
+
+    println!("cargo:rerun-if-changed=no_atomic.rs");
 }
diff --git a/third_party/rust/crossbeam-utils/no_atomic.rs b/third_party/rust/crossbeam-utils/no_atomic.rs
new file mode 100644
index 0000000000000000000000000000000000000000..522b3b8acd8965eb7b1499eda20eb35fcd88a489
--- /dev/null
+++ b/third_party/rust/crossbeam-utils/no_atomic.rs
@@ -0,0 +1,59 @@
+// This file is @generated by no_atomic.sh.
+// It is not intended for manual editing.
+
+const NO_ATOMIC_CAS: &[&str] = &[
+    "avr-unknown-gnu-atmega328",
+    "msp430-none-elf",
+    "riscv32i-unknown-none-elf",
+    "riscv32imc-unknown-none-elf",
+    "thumbv4t-none-eabi",
+    "thumbv6m-none-eabi",
+];
+#[allow(dead_code)]
+const NO_ATOMIC_64: &[&str] = &[
+    "arm-linux-androideabi",
+    "armebv7r-none-eabi",
+    "armebv7r-none-eabihf",
+    "armv4t-unknown-linux-gnueabi",
+    "armv5te-unknown-linux-gnueabi",
+    "armv5te-unknown-linux-musleabi",
+    "armv5te-unknown-linux-uclibceabi",
+    "armv7r-none-eabi",
+    "armv7r-none-eabihf",
+    "hexagon-unknown-linux-musl",
+    "mips-unknown-linux-gnu",
+    "mips-unknown-linux-musl",
+    "mips-unknown-linux-uclibc",
+    "mipsel-unknown-linux-gnu",
+    "mipsel-unknown-linux-musl",
+    "mipsel-unknown-linux-uclibc",
+    "mipsel-unknown-none",
+    "mipsisa32r6-unknown-linux-gnu",
+    "mipsisa32r6el-unknown-linux-gnu",
+    "powerpc-unknown-linux-gnu",
+    "powerpc-unknown-linux-gnuspe",
+    "powerpc-unknown-linux-musl",
+    "powerpc-unknown-netbsd",
+    "powerpc-unknown-openbsd",
+    "powerpc-wrs-vxworks",
+    "powerpc-wrs-vxworks-spe",
+    "riscv32gc-unknown-linux-gnu",
+    "riscv32gc-unknown-linux-musl",
+    "riscv32imac-unknown-none-elf",
+    "thumbv7em-none-eabi",
+    "thumbv7em-none-eabihf",
+    "thumbv7m-none-eabi",
+    "thumbv8m.base-none-eabi",
+    "thumbv8m.main-none-eabi",
+    "thumbv8m.main-none-eabihf",
+    "mipsel-sony-psp",
+    "thumbv4t-none-eabi",
+    "thumbv6m-none-eabi",
+];
+#[allow(dead_code)]
+const NO_ATOMIC: &[&str] = &[
+    "avr-unknown-gnu-atmega328",
+    "msp430-none-elf",
+    "riscv32i-unknown-none-elf",
+    "riscv32imc-unknown-none-elf",
+];
diff --git a/third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs b/third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs
index e8f6804cfd274f0a9196f26af42dfee99a7a7ed7..1a1c46460187494af42996acc43f1e63ec4ebd6a 100644
--- a/third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils/src/atomic/atomic_cell.rs
@@ -2,15 +2,19 @@
 #![allow(clippy::unit_arg)]
 #![allow(clippy::let_unit_value)]
 
+use crate::primitive::sync::atomic::{self, AtomicBool};
 use core::cell::UnsafeCell;
 use core::fmt;
 use core::mem;
+use core::sync::atomic::Ordering;
+
+#[cfg(not(crossbeam_loom))]
 use core::ptr;
-use core::sync::atomic::{self, AtomicBool, Ordering};
 
 #[cfg(feature = "std")]
 use std::panic::{RefUnwindSafe, UnwindSafe};
 
+#[cfg(not(crossbeam_loom))]
 use super::seq_lock::SeqLock;
 
 /// A thread-safe mutable memory location.
@@ -213,6 +217,7 @@ impl<T: Copy + Eq> AtomicCell<T> {
     /// # Examples
     ///
     /// ```
+    /// # #![allow(deprecated)]
     /// use crossbeam_utils::atomic::AtomicCell;
     ///
     /// let a = AtomicCell::new(1);
@@ -223,6 +228,8 @@ impl<T: Copy + Eq> AtomicCell<T> {
     /// assert_eq!(a.compare_and_swap(1, 2), 1);
     /// assert_eq!(a.load(), 2);
     /// ```
+    // TODO: remove in the next major version.
+    #[deprecated(note = "Use `compare_exchange` instead")]
     pub fn compare_and_swap(&self, current: T, new: T) -> T {
         match self.compare_exchange(current, new) {
             Ok(v) => v,
@@ -251,6 +258,40 @@ impl<T: Copy + Eq> AtomicCell<T> {
     pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
         unsafe { atomic_compare_exchange_weak(self.value.get(), current, new) }
     }
+
+    /// Fetches the value, and applies a function to it that returns an optional
+    /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
+    /// `Err(previous_value)`.
+    ///
+    /// Note: This may call the function multiple times if the value has been changed from other threads in
+    /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
+    /// only once to the stored value.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use crossbeam_utils::atomic::AtomicCell;
+    ///
+    /// let a = AtomicCell::new(7);
+    /// assert_eq!(a.fetch_update(|_| None), Err(7));
+    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
+    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
+    /// assert_eq!(a.load(), 9);
+    /// ```
+    #[inline]
+    pub fn fetch_update<F>(&self, mut f: F) -> Result<T, T>
+    where
+        F: FnMut(T) -> Option<T>,
+    {
+        let mut prev = self.load();
+        while let Some(next) = f(prev) {
+            match self.compare_exchange(prev, next) {
+                x @ Ok(_) => return x,
+                Err(next_prev) => prev = next_prev,
+            }
+        }
+        Err(prev)
+    }
 }
 
 macro_rules! impl_arithmetic {
@@ -490,26 +531,19 @@ macro_rules! impl_arithmetic {
     };
 }
 
-#[cfg(has_atomic_u8)]
 impl_arithmetic!(u8, atomic::AtomicU8, "let a = AtomicCell::new(7u8);");
-#[cfg(has_atomic_u8)]
 impl_arithmetic!(i8, atomic::AtomicI8, "let a = AtomicCell::new(7i8);");
-#[cfg(has_atomic_u16)]
 impl_arithmetic!(u16, atomic::AtomicU16, "let a = AtomicCell::new(7u16);");
-#[cfg(has_atomic_u16)]
 impl_arithmetic!(i16, atomic::AtomicI16, "let a = AtomicCell::new(7i16);");
-#[cfg(has_atomic_u32)]
 impl_arithmetic!(u32, atomic::AtomicU32, "let a = AtomicCell::new(7u32);");
-#[cfg(has_atomic_u32)]
 impl_arithmetic!(i32, atomic::AtomicI32, "let a = AtomicCell::new(7i32);");
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_arithmetic!(u64, atomic::AtomicU64, "let a = AtomicCell::new(7u64);");
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_arithmetic!(i64, atomic::AtomicI64, "let a = AtomicCell::new(7i64);");
-#[cfg(has_atomic_u128)]
-impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
-#[cfg(has_atomic_u128)]
-impl_arithmetic!(i128, atomic::AtomicI128, "let  a = AtomicCell::new(7i128);");
+// TODO: AtomicU128 is unstable
+// impl_arithmetic!(u128, atomic::AtomicU128, "let a = AtomicCell::new(7u128);");
+// impl_arithmetic!(i128, atomic::AtomicI128, "let a = AtomicCell::new(7i128);");
 
 impl_arithmetic!(
     usize,
@@ -624,6 +658,7 @@ const fn can_transmute<A, B>() -> bool {
 /// scalability.
 #[inline]
 #[must_use]
+#[cfg(not(crossbeam_loom))]
 fn lock(addr: usize) -> &'static SeqLock {
     // The number of locks is a prime number because we want to make sure `addr % LEN` gets
     // dispersed across all locks.
@@ -769,6 +804,7 @@ impl AtomicUnit {
     #[inline]
     fn swap(&self, _val: (), _order: Ordering) {}
 
+    #[allow(clippy::unnecessary_wraps)] // This is intentional.
     #[inline]
     fn compare_exchange_weak(
         &self,
@@ -799,17 +835,17 @@ macro_rules! atomic {
             atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
             atomic!(@check, $t, atomic::AtomicUsize, $a, $atomic_op);
 
-            #[cfg(has_atomic_u8)]
             atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
-            #[cfg(has_atomic_u16)]
             atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
-            #[cfg(has_atomic_u32)]
             atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
-            #[cfg(has_atomic_u64)]
+            #[cfg(not(crossbeam_no_atomic_64))]
             atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
-            #[cfg(has_atomic_u128)]
-            atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
+            // TODO: AtomicU128 is unstable
+            // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
 
+            #[cfg(crossbeam_loom)]
+            unimplemented!("loom does not support non-atomic atomic ops");
+            #[cfg(not(crossbeam_loom))]
             break $fallback_op;
         }
     };
@@ -818,17 +854,15 @@ macro_rules! atomic {
 /// Returns `true` if operations on `AtomicCell<T>` are lock-free.
 const fn atomic_is_lock_free<T>() -> bool {
     // HACK(taiki-e): This is equivalent to `atomic! { T, _a, true, false }`, but can be used in const fn even in Rust 1.36.
-    let is_lock_free = can_transmute::<T, AtomicUnit>() | can_transmute::<T, atomic::AtomicUsize>();
-    #[cfg(has_atomic_u8)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU8>();
-    #[cfg(has_atomic_u16)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU16>();
-    #[cfg(has_atomic_u32)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU32>();
-    #[cfg(has_atomic_u64)]
+    let is_lock_free = can_transmute::<T, AtomicUnit>()
+        | can_transmute::<T, atomic::AtomicUsize>()
+        | can_transmute::<T, atomic::AtomicU8>()
+        | can_transmute::<T, atomic::AtomicU16>()
+        | can_transmute::<T, atomic::AtomicU32>();
+    #[cfg(not(crossbeam_no_atomic_64))]
     let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU64>();
-    #[cfg(has_atomic_u128)]
-    let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
+    // TODO: AtomicU128 is unstable
+    // let is_lock_free = is_lock_free | can_transmute::<T, atomic::AtomicU128>();
     is_lock_free
 }
 
diff --git a/third_party/rust/crossbeam-utils/src/atomic/consume.rs b/third_party/rust/crossbeam-utils/src/atomic/consume.rs
index 584fc34c1ae6fe147a418cd48fe396e7ed248f0f..277b370a554b0d81f97fd011381e32b19ac72255 100644
--- a/third_party/rust/crossbeam-utils/src/atomic/consume.rs
+++ b/third_party/rust/crossbeam-utils/src/atomic/consume.rs
@@ -1,5 +1,6 @@
 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
-use core::sync::atomic::compiler_fence;
+use crate::primitive::sync::atomic::compiler_fence;
+#[cfg(not(crossbeam_no_atomic))]
 use core::sync::atomic::Ordering;
 
 /// Trait which allows reading from primitive atomic types with "consume" ordering.
@@ -25,6 +26,7 @@ pub trait AtomicConsume {
     fn load_consume(&self) -> Self::Val;
 }
 
+#[cfg(not(crossbeam_no_atomic))]
 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
 macro_rules! impl_consume {
     () => {
@@ -37,6 +39,7 @@ macro_rules! impl_consume {
     };
 }
 
+#[cfg(not(crossbeam_no_atomic))]
 #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
 macro_rules! impl_consume {
     () => {
@@ -49,7 +52,13 @@ macro_rules! impl_consume {
 
 macro_rules! impl_atomic {
     ($atomic:ident, $val:ty) => {
-        impl AtomicConsume for ::core::sync::atomic::$atomic {
+        #[cfg(not(crossbeam_no_atomic))]
+        impl AtomicConsume for core::sync::atomic::$atomic {
+            type Val = $val;
+            impl_consume!();
+        }
+        #[cfg(crossbeam_loom)]
+        impl AtomicConsume for loom::sync::atomic::$atomic {
             type Val = $val;
             impl_consume!();
         }
@@ -59,24 +68,25 @@ macro_rules! impl_atomic {
 impl_atomic!(AtomicBool, bool);
 impl_atomic!(AtomicUsize, usize);
 impl_atomic!(AtomicIsize, isize);
-#[cfg(has_atomic_u8)]
 impl_atomic!(AtomicU8, u8);
-#[cfg(has_atomic_u8)]
 impl_atomic!(AtomicI8, i8);
-#[cfg(has_atomic_u16)]
 impl_atomic!(AtomicU16, u16);
-#[cfg(has_atomic_u16)]
 impl_atomic!(AtomicI16, i16);
-#[cfg(has_atomic_u32)]
 impl_atomic!(AtomicU32, u32);
-#[cfg(has_atomic_u32)]
 impl_atomic!(AtomicI32, i32);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_atomic!(AtomicU64, u64);
-#[cfg(has_atomic_u64)]
+#[cfg(not(crossbeam_no_atomic_64))]
 impl_atomic!(AtomicI64, i64);
 
-impl<T> AtomicConsume for ::core::sync::atomic::AtomicPtr<T> {
+#[cfg(not(crossbeam_no_atomic))]
+impl<T> AtomicConsume for core::sync::atomic::AtomicPtr<T> {
+    type Val = *mut T;
+    impl_consume!();
+}
+
+#[cfg(crossbeam_loom)]
+impl<T> AtomicConsume for loom::sync::atomic::AtomicPtr<T> {
     type Val = *mut T;
     impl_consume!();
 }
diff --git a/third_party/rust/crossbeam-utils/src/atomic/mod.rs b/third_party/rust/crossbeam-utils/src/atomic/mod.rs
index 7309c166d27732f58064fe78c8397957b7319343..fc713fcac667b50e2ac02270f807549e75f8e54a 100644
--- a/third_party/rust/crossbeam-utils/src/atomic/mod.rs
+++ b/third_party/rust/crossbeam-utils/src/atomic/mod.rs
@@ -1,8 +1,11 @@
 //! Atomic types.
+//!
+//! * [`AtomicCell`], a thread-safe mutable memory location.
+//! * [`AtomicConsume`], for reading from primitive atomic types with "consume" ordering.
 
-use cfg_if::cfg_if;
-
-cfg_if! {
+#[cfg(not(crossbeam_no_atomic_cas))]
+#[cfg(not(crossbeam_loom))]
+cfg_if::cfg_if! {
     // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap
     // around.
     //
@@ -20,8 +23,10 @@ cfg_if! {
     }
 }
 
+#[cfg(not(crossbeam_no_atomic_cas))]
 mod atomic_cell;
 mod consume;
 
+#[cfg(not(crossbeam_no_atomic_cas))]
 pub use self::atomic_cell::AtomicCell;
 pub use self::consume::AtomicConsume;
diff --git a/third_party/rust/crossbeam-utils/src/atomic/seq_lock.rs b/third_party/rust/crossbeam-utils/src/atomic/seq_lock.rs
index a423bc0320b8aac14e437ac4daa5af22ced4b2f0..ff8defd26dab85c744fa1f3987f9d4c67dd568f1 100644
--- a/third_party/rust/crossbeam-utils/src/atomic/seq_lock.rs
+++ b/third_party/rust/crossbeam-utils/src/atomic/seq_lock.rs
@@ -4,7 +4,7 @@ use core::sync::atomic::{self, AtomicUsize, Ordering};
 use crate::Backoff;
 
 /// A simple stamped lock.
-pub struct SeqLock {
+pub(crate) struct SeqLock {
     /// The current state of the lock.
     ///
     /// All bits except the least significant one hold the current stamp. When locked, the state
@@ -13,7 +13,7 @@ pub struct SeqLock {
 }
 
 impl SeqLock {
-    pub const fn new() -> Self {
+    pub(crate) const fn new() -> Self {
         Self {
             state: AtomicUsize::new(0),
         }
@@ -23,7 +23,7 @@ impl SeqLock {
     ///
     /// This method should be called before optimistic reads.
     #[inline]
-    pub fn optimistic_read(&self) -> Option<usize> {
+    pub(crate) fn optimistic_read(&self) -> Option<usize> {
         let state = self.state.load(Ordering::Acquire);
         if state == 1 {
             None
@@ -37,14 +37,14 @@ impl SeqLock {
     /// This method should be called after optimistic reads to check whether they are valid. The
     /// argument `stamp` should correspond to the one returned by method `optimistic_read`.
     #[inline]
-    pub fn validate_read(&self, stamp: usize) -> bool {
+    pub(crate) fn validate_read(&self, stamp: usize) -> bool {
         atomic::fence(Ordering::Acquire);
         self.state.load(Ordering::Relaxed) == stamp
     }
 
     /// Grabs the lock for writing.
     #[inline]
-    pub fn write(&'static self) -> SeqLockWriteGuard {
+    pub(crate) fn write(&'static self) -> SeqLockWriteGuard {
         let backoff = Backoff::new();
         loop {
             let previous = self.state.swap(1, Ordering::Acquire);
@@ -64,7 +64,7 @@ impl SeqLock {
 }
 
 /// An RAII guard that releases the lock and increments the stamp when dropped.
-pub struct SeqLockWriteGuard {
+pub(crate) struct SeqLockWriteGuard {
     /// The parent lock.
     lock: &'static SeqLock,
 
@@ -75,7 +75,7 @@ pub struct SeqLockWriteGuard {
 impl SeqLockWriteGuard {
     /// Releases the lock without incrementing the stamp.
     #[inline]
-    pub fn abort(self) {
+    pub(crate) fn abort(self) {
         self.lock.state.store(self.state, Ordering::Release);
 
         // We specifically don't want to call drop(), since that's
diff --git a/third_party/rust/crossbeam-utils/src/atomic/seq_lock_wide.rs b/third_party/rust/crossbeam-utils/src/atomic/seq_lock_wide.rs
index 871a93d28b57018f22480b81668a8c13d794cab3..ef5d94a45413dce5c36f3533403601ca44ef1a70 100644
--- a/third_party/rust/crossbeam-utils/src/atomic/seq_lock_wide.rs
+++ b/third_party/rust/crossbeam-utils/src/atomic/seq_lock_wide.rs
@@ -7,7 +7,7 @@ use crate::Backoff;
 ///
 /// The state is represented as two `AtomicUsize`: `state_hi` for high bits and `state_lo` for low
 /// bits.
-pub struct SeqLock {
+pub(crate) struct SeqLock {
     /// The high bits of the current state of the lock.
     state_hi: AtomicUsize,
 
@@ -19,7 +19,7 @@ pub struct SeqLock {
 }
 
 impl SeqLock {
-    pub const fn new() -> Self {
+    pub(crate) const fn new() -> Self {
         Self {
             state_hi: AtomicUsize::new(0),
             state_lo: AtomicUsize::new(0),
@@ -30,7 +30,7 @@ impl SeqLock {
     ///
     /// This method should be called before optimistic reads.
     #[inline]
-    pub fn optimistic_read(&self) -> Option<(usize, usize)> {
+    pub(crate) fn optimistic_read(&self) -> Option<(usize, usize)> {
         // The acquire loads from `state_hi` and `state_lo` synchronize with the release stores in
         // `SeqLockWriteGuard::drop`.
         //
@@ -51,7 +51,7 @@ impl SeqLock {
     /// This method should be called after optimistic reads to check whether they are valid. The
     /// argument `stamp` should correspond to the one returned by method `optimistic_read`.
     #[inline]
-    pub fn validate_read(&self, stamp: (usize, usize)) -> bool {
+    pub(crate) fn validate_read(&self, stamp: (usize, usize)) -> bool {
         // Thanks to the fence, if we're noticing any modification to the data at the critical
         // section of `(a, b)`, then the critical section's write of 1 to state_lo should be
         // visible.
@@ -76,7 +76,7 @@ impl SeqLock {
 
     /// Grabs the lock for writing.
     #[inline]
-    pub fn write(&'static self) -> SeqLockWriteGuard {
+    pub(crate) fn write(&'static self) -> SeqLockWriteGuard {
         let backoff = Backoff::new();
         loop {
             let previous = self.state_lo.swap(1, Ordering::Acquire);
@@ -98,7 +98,7 @@ impl SeqLock {
 }
 
 /// An RAII guard that releases the lock and increments the stamp when dropped.
-pub struct SeqLockWriteGuard {
+pub(crate) struct SeqLockWriteGuard {
     /// The parent lock.
     lock: &'static SeqLock,
 
@@ -109,7 +109,7 @@ pub struct SeqLockWriteGuard {
 impl SeqLockWriteGuard {
     /// Releases the lock without incrementing the stamp.
     #[inline]
-    pub fn abort(self) {
+    pub(crate) fn abort(self) {
         self.lock.state_lo.store(self.state_lo, Ordering::Release);
         mem::forget(self);
     }
diff --git a/third_party/rust/crossbeam-utils/src/backoff.rs b/third_party/rust/crossbeam-utils/src/backoff.rs
index 2391dd1cead4a76f1a21d1bcca1da52861b5e13f..1012f06b238a9f25fabfec6d949e6cb0ed0cd6ed 100644
--- a/third_party/rust/crossbeam-utils/src/backoff.rs
+++ b/third_party/rust/crossbeam-utils/src/backoff.rs
@@ -1,6 +1,6 @@
+use crate::primitive::sync::atomic;
 use core::cell::Cell;
 use core::fmt;
-use core::sync::atomic;
 
 const SPIN_LIMIT: u32 = 6;
 const YIELD_LIMIT: u32 = 10;
@@ -27,7 +27,7 @@ const YIELD_LIMIT: u32 = 10;
 ///     let backoff = Backoff::new();
 ///     loop {
 ///         let val = a.load(SeqCst);
-///         if a.compare_and_swap(val, val.wrapping_mul(b), SeqCst) == val {
+///         if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
 ///             return val;
 ///         }
 ///         backoff.spin();
@@ -131,7 +131,7 @@ impl Backoff {
     ///     let backoff = Backoff::new();
     ///     loop {
     ///         let val = a.load(SeqCst);
-    ///         if a.compare_and_swap(val, val.wrapping_mul(b), SeqCst) == val {
+    ///         if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
     ///             return val;
     ///         }
     ///         backoff.spin();
@@ -145,6 +145,9 @@ impl Backoff {
     #[inline]
     pub fn spin(&self) {
         for _ in 0..1 << self.step.get().min(SPIN_LIMIT) {
+            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+            // use [`core::hint::spin_loop`] instead.
+            #[allow(deprecated)]
             atomic::spin_loop_hint();
         }
 
@@ -205,11 +208,17 @@ impl Backoff {
     pub fn snooze(&self) {
         if self.step.get() <= SPIN_LIMIT {
             for _ in 0..1 << self.step.get() {
+                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+                // use [`core::hint::spin_loop`] instead.
+                #[allow(deprecated)]
                 atomic::spin_loop_hint();
             }
         } else {
             #[cfg(not(feature = "std"))]
             for _ in 0..1 << self.step.get() {
+                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+                // use [`core::hint::spin_loop`] instead.
+                #[allow(deprecated)]
                 atomic::spin_loop_hint();
             }
 
diff --git a/third_party/rust/crossbeam-utils/src/cache_padded.rs b/third_party/rust/crossbeam-utils/src/cache_padded.rs
index 62c686b7e3909f06d2ee0aabbd5fec8c48072b5d..822e831d16281f7f97e895c19e713911381c1c75 100644
--- a/third_party/rust/crossbeam-utils/src/cache_padded.rs
+++ b/third_party/rust/crossbeam-utils/src/cache_padded.rs
@@ -13,7 +13,9 @@ use core::ops::{Deref, DerefMut};
 ///
 /// Cache lines are assumed to be N bytes long, depending on the architecture:
 ///
-/// * On x86-64 and aarch64, N = 128.
+/// * On x86-64, aarch64, and powerpc64, N = 128.
+/// * On arm, mips, mips64, and riscv64, N = 32.
+/// * On s390x, N = 256.
 /// * On all others, N = 64.
 ///
 /// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
@@ -64,13 +66,63 @@ use core::ops::{Deref, DerefMut};
 // - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
 // - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
 //
-// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128 byte cache line size
+// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128-byte cache line size.
+//
 // Sources:
 // - https://www.mono-project.com/news/2016/09/12/arm64-icache/
 //
-#[cfg_attr(any(target_arch = "x86_64", target_arch = "aarch64"), repr(align(128)))]
+// powerpc64 has 128-byte cache line size.
+//
+// Sources:
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9
+#[cfg_attr(
+    any(
+        target_arch = "x86_64",
+        target_arch = "aarch64",
+        target_arch = "powerpc64",
+    ),
+    repr(align(128))
+)]
+// arm, mips, mips64, and riscv64 have 32-byte cache line size.
+//
+// Sources:
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
+#[cfg_attr(
+    any(
+        target_arch = "arm",
+        target_arch = "mips",
+        target_arch = "mips64",
+        target_arch = "riscv64",
+    ),
+    repr(align(32))
+)]
+// s390x has 256-byte cache line size.
+//
+// Sources:
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7
+#[cfg_attr(target_arch = "s390x", repr(align(256)))]
+// x86 and wasm have 64-byte cache line size.
+//
+// Sources:
+// - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9
+// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7
+//
+// All others are assumed to have 64-byte cache line size.
 #[cfg_attr(
-    not(any(target_arch = "x86_64", target_arch = "aarch64")),
+    not(any(
+        target_arch = "x86_64",
+        target_arch = "aarch64",
+        target_arch = "powerpc64",
+        target_arch = "arm",
+        target_arch = "mips",
+        target_arch = "mips64",
+        target_arch = "riscv64",
+        target_arch = "s390x",
+    )),
     repr(align(64))
 )]
 pub struct CachePadded<T> {
diff --git a/third_party/rust/crossbeam-utils/src/lib.rs b/third_party/rust/crossbeam-utils/src/lib.rs
index f2bd460b9d30d63d7796eadc6fd45fb6c9dabee8..191c5a17d15cdfac4f218ab7b4db70ec71f545fd 100644
--- a/third_party/rust/crossbeam-utils/src/lib.rs
+++ b/third_party/rust/crossbeam-utils/src/lib.rs
@@ -31,13 +31,59 @@
         allow(dead_code, unused_assignments, unused_variables)
     )
 ))]
-#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
+#![warn(
+    missing_docs,
+    missing_debug_implementations,
+    rust_2018_idioms,
+    unreachable_pub
+)]
 #![cfg_attr(not(feature = "std"), no_std)]
-#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]
-// matches! requires Rust 1.42
-#![allow(clippy::match_like_matches_macro)]
 
-#[cfg_attr(feature = "nightly", cfg(target_has_atomic = "ptr"))]
+#[cfg(crossbeam_loom)]
+#[allow(unused_imports)]
+mod primitive {
+    pub(crate) mod sync {
+        pub(crate) mod atomic {
+            pub(crate) use loom::sync::atomic::spin_loop_hint;
+            pub(crate) use loom::sync::atomic::{
+                AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
+                AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+            };
+
+            // FIXME: loom does not support compiler_fence at the moment.
+            // https://github.com/tokio-rs/loom/issues/117
+            // we use fence as a stand-in for compiler_fence for the time being.
+            // this may miss some races since fence is stronger than compiler_fence,
+            // but it's the best we can do for the time being.
+            pub(crate) use loom::sync::atomic::fence as compiler_fence;
+        }
+        pub(crate) use loom::sync::{Arc, Condvar, Mutex};
+    }
+}
+#[cfg(not(crossbeam_loom))]
+#[allow(unused_imports)]
+mod primitive {
+    pub(crate) mod sync {
+        pub(crate) mod atomic {
+            pub(crate) use core::sync::atomic::compiler_fence;
+            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+            // use [`core::hint::spin_loop`] instead.
+            #[allow(deprecated)]
+            pub(crate) use core::sync::atomic::spin_loop_hint;
+            #[cfg(not(crossbeam_no_atomic))]
+            pub(crate) use core::sync::atomic::{
+                AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
+                AtomicU8, AtomicUsize,
+            };
+            #[cfg(not(crossbeam_no_atomic_64))]
+            pub(crate) use core::sync::atomic::{AtomicI64, AtomicU64};
+        }
+
+        #[cfg(feature = "std")]
+        pub(crate) use std::sync::{Arc, Condvar, Mutex};
+    }
+}
+
 pub mod atomic;
 
 mod cache_padded;
@@ -51,6 +97,8 @@ use cfg_if::cfg_if;
 cfg_if! {
     if #[cfg(feature = "std")] {
         pub mod sync;
+
+        #[cfg(not(crossbeam_loom))]
         pub mod thread;
     }
 }
diff --git a/third_party/rust/crossbeam-utils/src/sync/mod.rs b/third_party/rust/crossbeam-utils/src/sync/mod.rs
index fd400d70e7ca0266e5e30c1f8975506d1b1112e7..eeb740c2cd0402e19821f7557317d7a5acb42e12 100644
--- a/third_party/rust/crossbeam-utils/src/sync/mod.rs
+++ b/third_party/rust/crossbeam-utils/src/sync/mod.rs
@@ -5,9 +5,11 @@
 //! * [`WaitGroup`], for synchronizing the beginning or end of some computation.
 
 mod parker;
+#[cfg(not(crossbeam_loom))]
 mod sharded_lock;
 mod wait_group;
 
 pub use self::parker::{Parker, Unparker};
+#[cfg(not(crossbeam_loom))]
 pub use self::sharded_lock::{ShardedLock, ShardedLockReadGuard, ShardedLockWriteGuard};
 pub use self::wait_group::WaitGroup;
diff --git a/third_party/rust/crossbeam-utils/src/sync/parker.rs b/third_party/rust/crossbeam-utils/src/sync/parker.rs
index fc13d2e967df8dd85ecc3ec5778b991715796599..aefa5152738f3a469138ab6966c5fdbb05e8a004 100644
--- a/third_party/rust/crossbeam-utils/src/sync/parker.rs
+++ b/third_party/rust/crossbeam-utils/src/sync/parker.rs
@@ -1,20 +1,19 @@
+use crate::primitive::sync::atomic::AtomicUsize;
+use crate::primitive::sync::{Arc, Condvar, Mutex};
+use core::sync::atomic::Ordering::SeqCst;
 use std::fmt;
 use std::marker::PhantomData;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering::SeqCst;
-use std::sync::{Arc, Condvar, Mutex};
-use std::time::Duration;
+use std::time::{Duration, Instant};
 
 /// A thread parking primitive.
 ///
 /// Conceptually, each `Parker` has an associated token which is initially not present:
 ///
 /// * The [`park`] method blocks the current thread unless or until the token is available, at
-///   which point it automatically consumes the token. It may also return *spuriously*, without
-///   consuming the token.
+///   which point it automatically consumes the token.
 ///
-/// * The [`park_timeout`] method works the same as [`park`], but blocks for a specified maximum
-///   time.
+/// * The [`park_timeout`] and [`park_deadline`] methods work the same as [`park`], but block for
+///   a specified maximum time.
 ///
 /// * The [`unpark`] method atomically makes the token available if it wasn't already. Because the
 ///   token is initially absent, [`unpark`] followed by [`park`] will result in the second call
@@ -43,13 +42,13 @@ use std::time::Duration;
 ///     u.unpark();
 /// });
 ///
-/// // Wakes up when `u.unpark()` provides the token, but may also wake up
-/// // spuriously before that without consuming the token.
+/// // Wakes up when `u.unpark()` provides the token.
 /// p.park();
 /// ```
 ///
 /// [`park`]: Parker::park
 /// [`park_timeout`]: Parker::park_timeout
+/// [`park_deadline`]: Parker::park_deadline
 /// [`unpark`]: Unparker::unpark
 pub struct Parker {
     unparker: Unparker,
@@ -90,9 +89,6 @@ impl Parker {
 
     /// Blocks the current thread until the token is made available.
     ///
-    /// A call to `park` may wake up spuriously without consuming the token, and callers should be
-    /// prepared for this possibility.
-    ///
     /// # Examples
     ///
     /// ```
@@ -113,9 +109,6 @@ impl Parker {
 
     /// Blocks the current thread until the token is made available, but only for a limited time.
     ///
-    /// A call to `park_timeout` may wake up spuriously without consuming the token, and callers
-    /// should be prepared for this possibility.
-    ///
     /// # Examples
     ///
     /// ```
@@ -128,7 +121,25 @@ impl Parker {
     /// p.park_timeout(Duration::from_millis(500));
     /// ```
     pub fn park_timeout(&self, timeout: Duration) {
-        self.unparker.inner.park(Some(timeout));
+        self.park_deadline(Instant::now() + timeout)
+    }
+
+    /// Blocks the current thread until the token is made available, or until a certain deadline.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::{Duration, Instant};
+    /// use crossbeam_utils::sync::Parker;
+    ///
+    /// let p = Parker::new();
+    /// let deadline = Instant::now() + Duration::from_millis(500);
+    ///
+    /// // Waits for the token to become available, but will not wait longer than 500 ms.
+    /// p.park_deadline(deadline);
+    /// ```
+    pub fn park_deadline(&self, deadline: Instant) {
+        self.unparker.inner.park(Some(deadline))
     }
 
     /// Returns a reference to an associated [`Unparker`].
@@ -227,8 +238,7 @@ impl Unparker {
     ///     u.unpark();
     /// });
     ///
-    /// // Wakes up when `u.unpark()` provides the token, but may also wake up
-    /// // spuriously before that without consuming the token.
+    /// // Wakes up when `u.unpark()` provides the token.
     /// p.park();
     /// ```
     ///
@@ -302,7 +312,7 @@ struct Inner {
 }
 
 impl Inner {
-    fn park(&self, timeout: Option<Duration>) {
+    fn park(&self, deadline: Option<Instant>) {
         // If we were previously notified then we consume this notification and return quickly.
         if self
             .state
@@ -313,8 +323,8 @@ impl Inner {
         }
 
         // If the timeout is zero, then there is no need to actually block.
-        if let Some(ref dur) = timeout {
-            if *dur == Duration::from_millis(0) {
+        if let Some(deadline) = deadline {
+            if deadline <= Instant::now() {
                 return;
             }
         }
@@ -338,40 +348,42 @@ impl Inner {
             Err(n) => panic!("inconsistent park_timeout state: {}", n),
         }
 
-        match timeout {
-            None => {
-                loop {
-                    // Block the current thread on the conditional variable.
-                    m = self.cvar.wait(m).unwrap();
-
-                    if self
-                        .state
-                        .compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst)
-                        .is_ok()
-                    {
-                        // got a notification
-                        return;
+        loop {
+            // Block the current thread on the conditional variable.
+            m = match deadline {
+                None => self.cvar.wait(m).unwrap(),
+                Some(deadline) => {
+                    let now = Instant::now();
+                    if now < deadline {
+                        // We could check for a timeout here, in the return value of wait_timeout,
+                        // but in the case that a timeout and an unpark arrive simultaneously, we
+                        // prefer to report the former.
+                        self.cvar.wait_timeout(m, deadline - now).unwrap().0
+                    } else {
+                        // We've timed out; swap out the state back to empty on our way out
+                        match self.state.swap(EMPTY, SeqCst) {
+                            NOTIFIED | PARKED => return,
+                            n => panic!("inconsistent park_timeout state: {}", n),
+                        };
                     }
-
-                    // spurious wakeup, go back to sleep
                 }
-            }
-            Some(timeout) => {
-                // Wait with a timeout, and if we spuriously wake up or otherwise wake up from a
-                // notification we just want to unconditionally set `state` back to `EMPTY`, either
-                // consuming a notification or un-flagging ourselves as parked.
-                let (_m, _result) = self.cvar.wait_timeout(m, timeout).unwrap();
+            };
 
-                match self.state.swap(EMPTY, SeqCst) {
-                    NOTIFIED => {} // got a notification
-                    PARKED => {}   // no notification
-                    n => panic!("inconsistent park_timeout state: {}", n),
-                }
+            if self
+                .state
+                .compare_exchange(NOTIFIED, EMPTY, SeqCst, SeqCst)
+                .is_ok()
+            {
+                // got a notification
+                return;
             }
+
+            // Spurious wakeup, go back to sleep. Alternatively, if we timed out, it will be caught
+            // in the branch above, when we discover the deadline is in the past
         }
     }
 
-    pub fn unpark(&self) {
+    pub(crate) fn unpark(&self) {
         // To ensure the unparked thread will observe any writes we made before this call, we must
         // perform a release operation that `park` can synchronize with. To do that we must write
         // `NOTIFIED` even if `state` is already `NOTIFIED`. That is why this must be a swap rather
diff --git a/third_party/rust/crossbeam-utils/src/sync/wait_group.rs b/third_party/rust/crossbeam-utils/src/sync/wait_group.rs
index cd7af12a369e2db8e6b4a0616731467068ab9bba..4206ee42b7b370bf1645888a819a1c4a7ac152a6 100644
--- a/third_party/rust/crossbeam-utils/src/sync/wait_group.rs
+++ b/third_party/rust/crossbeam-utils/src/sync/wait_group.rs
@@ -1,8 +1,8 @@
 // Necessary for using `Mutex<usize>` for conditional variables
 #![allow(clippy::mutex_atomic)]
 
+use crate::primitive::sync::{Arc, Condvar, Mutex};
 use std::fmt;
-use std::sync::{Arc, Condvar, Mutex};
 
 /// Enables threads to synchronize the beginning or end of some computation.
 ///
diff --git a/third_party/rust/crossbeam-utils/src/thread.rs b/third_party/rust/crossbeam-utils/src/thread.rs
index ab91be72d19c165be04c2ef82f427c6a265bd251..c57d076fbe2148a62724b1ee92772ffa05ffc607 100644
--- a/third_party/rust/crossbeam-utils/src/thread.rs
+++ b/third_party/rust/crossbeam-utils/src/thread.rs
@@ -110,8 +110,6 @@
 //!     });
 //! }).unwrap();
 //! ```
-//!
-//! [`std::thread::spawn`]: std::thread::spawn
 
 use std::fmt;
 use std::io;
@@ -572,7 +570,6 @@ cfg_if! {
             }
         }
 
-        #[cfg(windows)]
         impl<T> IntoRawHandle for ScopedJoinHandle<'_, T> {
             fn into_raw_handle(self) -> RawHandle {
                 self.as_raw_handle()
diff --git a/third_party/rust/crossbeam-utils/tests/atomic_cell.rs b/third_party/rust/crossbeam-utils/tests/atomic_cell.rs
index 3d91d81d69589ea3770b42cbc9002ed51494ba59..28208ee7698c5e7d9b00d1c69e78cb375c8831d3 100644
--- a/third_party/rust/crossbeam-utils/tests/atomic_cell.rs
+++ b/third_party/rust/crossbeam-utils/tests/atomic_cell.rs
@@ -1,3 +1,4 @@
+use std::mem;
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
 
@@ -8,18 +9,47 @@ fn is_lock_free() {
     struct UsizeWrap(usize);
     struct U8Wrap(bool);
     struct I16Wrap(i16);
-
-    assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
-    assert_eq!(AtomicCell::<isize>::is_lock_free(), true);
-    assert_eq!(AtomicCell::<UsizeWrap>::is_lock_free(), true);
-
-    assert_eq!(AtomicCell::<u8>::is_lock_free(), cfg!(has_atomic_u8));
-    assert_eq!(AtomicCell::<bool>::is_lock_free(), cfg!(has_atomic_u8));
-    assert_eq!(AtomicCell::<U8Wrap>::is_lock_free(), cfg!(has_atomic_u8));
-
-    assert_eq!(AtomicCell::<I16Wrap>::is_lock_free(), cfg!(has_atomic_u16));
-
-    assert_eq!(AtomicCell::<u128>::is_lock_free(), cfg!(has_atomic_u128));
+    #[repr(align(8))]
+    struct U64Align8(u64);
+
+    assert!(AtomicCell::<usize>::is_lock_free());
+    assert!(AtomicCell::<isize>::is_lock_free());
+    assert!(AtomicCell::<UsizeWrap>::is_lock_free());
+
+    assert!(AtomicCell::<()>::is_lock_free());
+
+    assert!(AtomicCell::<u8>::is_lock_free());
+    assert!(AtomicCell::<i8>::is_lock_free());
+    assert!(AtomicCell::<bool>::is_lock_free());
+    assert!(AtomicCell::<U8Wrap>::is_lock_free());
+
+    assert!(AtomicCell::<u16>::is_lock_free());
+    assert!(AtomicCell::<i16>::is_lock_free());
+    assert!(AtomicCell::<I16Wrap>::is_lock_free());
+
+    assert!(AtomicCell::<u32>::is_lock_free());
+    assert!(AtomicCell::<i32>::is_lock_free());
+
+    // Sizes of both types must be equal, and the alignment of `u64` must be greater or equal than
+    // that of `AtomicU64`. In i686-unknown-linux-gnu, the alignment of `u64` is `4` and alignment
+    // of `AtomicU64` is `8`, so `AtomicCell<u64>` is not lock-free.
+    assert_eq!(
+        AtomicCell::<u64>::is_lock_free(),
+        cfg!(not(crossbeam_no_atomic_64))
+            && cfg!(any(
+                target_pointer_width = "64",
+                target_pointer_width = "128"
+            ))
+    );
+    assert_eq!(mem::size_of::<U64Align8>(), 8);
+    assert_eq!(mem::align_of::<U64Align8>(), 8);
+    assert_eq!(
+        AtomicCell::<U64Align8>::is_lock_free(),
+        cfg!(not(crossbeam_no_atomic_64))
+    );
+
+    // AtomicU128 is unstable
+    assert!(!AtomicCell::<u128>::is_lock_free());
 }
 
 #[test]
diff --git a/third_party/rust/crossbeam-utils/tests/cache_padded.rs b/third_party/rust/crossbeam-utils/tests/cache_padded.rs
index be90cbe91da1c0e568c39d1c384263cc5355072e..86e9a7709c67154182853ad4513457b56b0c6fb1 100644
--- a/third_party/rust/crossbeam-utils/tests/cache_padded.rs
+++ b/third_party/rust/crossbeam-utils/tests/cache_padded.rs
@@ -27,7 +27,9 @@ fn distance() {
     let arr = [CachePadded::new(17u8), CachePadded::new(37u8)];
     let a = &*arr[0] as *const u8;
     let b = &*arr[1] as *const u8;
-    assert!(unsafe { a.offset(64) } <= b);
+    let align = mem::align_of::<CachePadded<()>>();
+    assert!(align >= 32);
+    assert_eq!(unsafe { a.add(align) }, b);
 }
 
 #[test]
@@ -83,6 +85,7 @@ fn drops() {
     assert_eq!(count.get(), 2);
 }
 
+#[allow(clippy::clone_on_copy)] // This is intentional.
 #[test]
 fn clone() {
     let a = CachePadded::new(17);
diff --git a/third_party/rust/crossbeam-utils/tests/parker.rs b/third_party/rust/crossbeam-utils/tests/parker.rs
index f657eb1cf015353257f3c0a0b32a36901e50db00..2bf9c37d491e65a3786b41236bfdbdb0c4ef588a 100644
--- a/third_party/rust/crossbeam-utils/tests/parker.rs
+++ b/third_party/rust/crossbeam-utils/tests/parker.rs
@@ -18,7 +18,7 @@ fn park_timeout_unpark_before() {
 fn park_timeout_unpark_not_called() {
     let p = Parker::new();
     for _ in 0..10 {
-        p.park_timeout(Duration::from_millis(10));
+        p.park_timeout(Duration::from_millis(10))
     }
 }
 
@@ -34,7 +34,7 @@ fn park_timeout_unpark_called_other_thread() {
                 u.unpark();
             });
 
-            p.park_timeout(Duration::from_millis(u32::MAX as u64));
+            p.park_timeout(Duration::from_millis(u32::MAX as u64))
         })
         .unwrap();
     }
diff --git a/third_party/rust/crossbeam-utils/tests/sharded_lock.rs b/third_party/rust/crossbeam-utils/tests/sharded_lock.rs
index 73bd489d3c2b306c5f0b72825feb3005352b37d5..b46d64a76bf5837989036f3763eab0e318939851 100644
--- a/third_party/rust/crossbeam-utils/tests/sharded_lock.rs
+++ b/third_party/rust/crossbeam-utils/tests/sharded_lock.rs
@@ -138,7 +138,7 @@ fn arc() {
 fn arc_access_in_unwind() {
     let arc = Arc::new(ShardedLock::new(1));
     let arc2 = arc.clone();
-    let _ = thread::spawn(move || -> () {
+    let _ = thread::spawn(move || {
         struct Unwinder {
             i: Arc<ShardedLock<isize>>,
         }
@@ -176,11 +176,8 @@ fn try_write() {
     let write_result = lock.try_write();
     match write_result {
         Err(TryLockError::WouldBlock) => (),
-        Ok(_) => assert!(
-            false,
-            "try_write should not succeed while read_guard is in scope"
-        ),
-        Err(_) => assert!(false, "unexpected error"),
+        Ok(_) => panic!("try_write should not succeed while read_guard is in scope"),
+        Err(_) => panic!("unexpected error"),
     }
 
     drop(read_guard);