diff --git a/.cargo/config.in b/.cargo/config.in
index 0050ee9e13191117d1b48f391904e70b57fde6cc..1c4008d9a49a848494fc2c949110b7b1114ca5a1 100644
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -40,7 +40,7 @@ rev = "e012b2151fb6f0ffd50e91baa7756e77a3c416d9"
 [source."https://github.com/mozilla/audioipc-2"]
 git = "https://github.com/mozilla/audioipc-2"
 replace-with = "vendored-sources"
-rev = "405b8208a8fb32e13db87c252aba9b371ae47859"
+rev = "c144368c4e084ec0f076af6262970655c2d99e8d"
 
 [source."https://github.com/mozilla/application-services"]
 git = "https://github.com/mozilla/application-services"
@@ -60,7 +60,7 @@ rev = "21c26326f5f45f415c49eac4ba5bc41a2f961321"
 [source."https://github.com/kinetiknz/audioipc-2"]
 git = "https://github.com/kinetiknz/audioipc-2"
 replace-with = "vendored-sources"
-rev = "f8f611808168b7b1395b2e5dc17e5e6e2b975c6d"
+rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9"
 
 [source."https://github.com/jfkthame/mapped_hyph.git"]
 git = "https://github.com/jfkthame/mapped_hyph.git"
diff --git a/Cargo.lock b/Cargo.lock
index 1cce624d1ec86fd3eeee77727489e291f98d8b5b..7ed4c0b49a76f1120584a28c8e5ef6a9092968f8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -206,7 +206,7 @@ dependencies = [
 [[package]]
 name = "audioipc"
 version = "0.2.5"
-source = "git+https://github.com/mozilla/audioipc-2?rev=405b8208a8fb32e13db87c252aba9b371ae47859#405b8208a8fb32e13db87c252aba9b371ae47859"
+source = "git+https://github.com/mozilla/audioipc-2?rev=c144368c4e084ec0f076af6262970655c2d99e8d#c144368c4e084ec0f076af6262970655c2d99e8d"
 dependencies = [
  "ashmem",
  "audio_thread_priority",
@@ -235,7 +235,7 @@ dependencies = [
 [[package]]
 name = "audioipc-client"
 version = "0.4.0"
-source = "git+https://github.com/mozilla/audioipc-2?rev=405b8208a8fb32e13db87c252aba9b371ae47859#405b8208a8fb32e13db87c252aba9b371ae47859"
+source = "git+https://github.com/mozilla/audioipc-2?rev=c144368c4e084ec0f076af6262970655c2d99e8d#c144368c4e084ec0f076af6262970655c2d99e8d"
 dependencies = [
  "audio_thread_priority",
  "audioipc",
@@ -249,7 +249,7 @@ dependencies = [
 [[package]]
 name = "audioipc-server"
 version = "0.2.3"
-source = "git+https://github.com/mozilla/audioipc-2?rev=405b8208a8fb32e13db87c252aba9b371ae47859#405b8208a8fb32e13db87c252aba9b371ae47859"
+source = "git+https://github.com/mozilla/audioipc-2?rev=c144368c4e084ec0f076af6262970655c2d99e8d#c144368c4e084ec0f076af6262970655c2d99e8d"
 dependencies = [
  "audio_thread_priority",
  "audioipc",
@@ -265,7 +265,7 @@ dependencies = [
 [[package]]
 name = "audioipc2"
 version = "0.5.0"
-source = "git+https://github.com/kinetiknz/audioipc-2?rev=f8f611808168b7b1395b2e5dc17e5e6e2b975c6d#f8f611808168b7b1395b2e5dc17e5e6e2b975c6d"
+source = "git+https://github.com/kinetiknz/audioipc-2?rev=85e9839059f4bf8f68130825b8fd02c39a6a51b9#85e9839059f4bf8f68130825b8fd02c39a6a51b9"
 dependencies = [
  "arrayvec 0.7.2",
  "ashmem",
@@ -291,7 +291,7 @@ dependencies = [
 [[package]]
 name = "audioipc2-client"
 version = "0.5.0"
-source = "git+https://github.com/kinetiknz/audioipc-2?rev=f8f611808168b7b1395b2e5dc17e5e6e2b975c6d#f8f611808168b7b1395b2e5dc17e5e6e2b975c6d"
+source = "git+https://github.com/kinetiknz/audioipc-2?rev=85e9839059f4bf8f68130825b8fd02c39a6a51b9#85e9839059f4bf8f68130825b8fd02c39a6a51b9"
 dependencies = [
  "audio_thread_priority",
  "audioipc2",
@@ -302,7 +302,7 @@ dependencies = [
 [[package]]
 name = "audioipc2-server"
 version = "0.5.0"
-source = "git+https://github.com/kinetiknz/audioipc-2?rev=f8f611808168b7b1395b2e5dc17e5e6e2b975c6d#f8f611808168b7b1395b2e5dc17e5e6e2b975c6d"
+source = "git+https://github.com/kinetiknz/audioipc-2?rev=85e9839059f4bf8f68130825b8fd02c39a6a51b9#85e9839059f4bf8f68130825b8fd02c39a6a51b9"
 dependencies = [
  "audio_thread_priority",
  "audioipc2",
@@ -1472,9 +1472,12 @@ dependencies = [
 
 [[package]]
 name = "error-chain"
-version = "0.11.0"
+version = "0.12.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
+checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
+dependencies = [
+ "version_check",
+]
 
 [[package]]
 name = "error-support"
diff --git a/third_party/rust/audioipc-client/.cargo-checksum.json b/third_party/rust/audioipc-client/.cargo-checksum.json
index 9566e62bb3ece1a95767f687814bd7cfa504ea08..3b0d6f6f0515655084801c494787b1968eb0ff9b 100644
--- a/third_party/rust/audioipc-client/.cargo-checksum.json
+++ b/third_party/rust/audioipc-client/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"146b0f913403605a3afcd378e8b0b4240ba39a7bc7b7ce7613d7928badc8c756","cbindgen.toml":"bd89c5a9f52395b1c703ff04d1c0019dc3c92b691d571ae503c4b85753a44a39","src/context.rs":"89e2929aa2ba4bddcec6dd4a4511f528c681b7717adbaa7b7df4378c8e3c4d1c","src/lib.rs":"7016a5de8770d3269e62dd7ad096fdd00cf821febf916bbc3163225cf6a53002","src/send_recv.rs":"064a657c845762be1dbcbbfc18b3f8a51582eb540def8d2ceecf200184ad4f7a","src/stream.rs":"f493ddc3ae950fc18fe42249b13194bc0a80bd0ce88bc8c7d3295f9ee10a932e"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"146b0f913403605a3afcd378e8b0b4240ba39a7bc7b7ce7613d7928badc8c756","cbindgen.toml":"bd89c5a9f52395b1c703ff04d1c0019dc3c92b691d571ae503c4b85753a44a39","src/context.rs":"6c50d02883421c3dc7de70721a099636dc9ae2285fb5a86279868b1c840630f2","src/lib.rs":"7016a5de8770d3269e62dd7ad096fdd00cf821febf916bbc3163225cf6a53002","src/send_recv.rs":"064a657c845762be1dbcbbfc18b3f8a51582eb540def8d2ceecf200184ad4f7a","src/stream.rs":"f493ddc3ae950fc18fe42249b13194bc0a80bd0ce88bc8c7d3295f9ee10a932e"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc-client/src/context.rs b/third_party/rust/audioipc-client/src/context.rs
index 3ed57f7b897ec931cd4994ac4535e44125c0046f..2737d37c081e610675097938906ce0d26d386ad6 100644
--- a/third_party/rust/audioipc-client/src/context.rs
+++ b/third_party/rust/audioipc-client/src/context.rs
@@ -279,13 +279,11 @@ impl ContextOps for ClientContext {
         collection: &DeviceCollectionRef,
     ) -> Result<()> {
         assert_not_in_callback();
-        let v: Vec<ffi::cubeb_device_info> = match send_recv!(self.rpc(),
-                             ContextGetDeviceEnumeration(devtype.bits()) =>
-                             ContextEnumeratedDevices())
-        {
-            Ok(mut v) => v.drain(..).map(|i| i.into()).collect(),
-            Err(e) => return Err(e),
-        };
+        let v: Vec<ffi::cubeb_device_info> = send_recv!(
+            self.rpc(), ContextGetDeviceEnumeration(devtype.bits()) => ContextEnumeratedDevices())?
+        .into_iter()
+        .map(|i| i.into())
+        .collect();
         let mut vs = v.into_boxed_slice();
         let coll = unsafe { &mut *collection.as_ptr() };
         coll.device = vs.as_mut_ptr();
diff --git a/third_party/rust/audioipc-server/.cargo-checksum.json b/third_party/rust/audioipc-server/.cargo-checksum.json
index ed45e3c361b5d51e7471fdedd84bb28e67265d33..8fc1af503e80d493f112da3e3cbfd8f5dd17b9df 100644
--- a/third_party/rust/audioipc-server/.cargo-checksum.json
+++ b/third_party/rust/audioipc-server/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"272aa1fcd2a9523075d2ca5734ed7f1fbb786ed9d92483bf96e70b8d60882dd0","cbindgen.toml":"bd89c5a9f52395b1c703ff04d1c0019dc3c92b691d571ae503c4b85753a44a39","src/lib.rs":"bb467df305bdb1403ffffd7960c5e55c14813d5098f0d88051d0c7542ed059dd","src/server.rs":"1fa365b9329d1873fb51893872a1e99ac86087428ca3bd6959611f3bd6d9549a"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"cdf9741a48d59b34f2e132c06c4610f0e8b089b037ceb2bbd7281da482f495df","cbindgen.toml":"bd89c5a9f52395b1c703ff04d1c0019dc3c92b691d571ae503c4b85753a44a39","src/lib.rs":"bb467df305bdb1403ffffd7960c5e55c14813d5098f0d88051d0c7542ed059dd","src/server.rs":"1fa365b9329d1873fb51893872a1e99ac86087428ca3bd6959611f3bd6d9549a"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc-server/Cargo.toml b/third_party/rust/audioipc-server/Cargo.toml
index d4dac715eb9d2e6dc6cc8c820bb9bfdbf8f2a3c4..be5fa69dc83c93e5f620434b9e6bdd6ee55409d5 100644
--- a/third_party/rust/audioipc-server/Cargo.toml
+++ b/third_party/rust/audioipc-server/Cargo.toml
@@ -19,7 +19,7 @@ slab = "0.4"
 tokio = "0.1"
 
 [dependencies.error-chain]
-version = "0.11.0"
+version = "0.12.0"
 default-features = false
 
 [dependencies.audio_thread_priority]
diff --git a/third_party/rust/audioipc/.cargo-checksum.json b/third_party/rust/audioipc/.cargo-checksum.json
index 0436d69c53677eb340c29c128b1e26f105344ecd..555308729aba87394800b3c8439a9186dee2f1e8 100644
--- a/third_party/rust/audioipc/.cargo-checksum.json
+++ b/third_party/rust/audioipc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c88c16f6f19e8028533a1bdb5bbdd88abe91f66903614ee1e5ee71d54492aabe","build.rs":"3f061cf9a989f63a71c693a543d26f7003e8b643c39c23ea555110252a2c39d2","src/async_msg.rs":"27c5c8215bcbe1364947065ac78198bcd4be7fbae0f5e49ea776cb454c5a6d2c","src/cmsg.rs":"97d8fe99ef94f75db9ed26cb4cf6faf9fbbc913cfa4152a8774ff4e76aead620","src/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/codec.rs":"2e0a05968e07617adc6be0cbf04962c952c621e118f0db308eeeed5ccea4dfce","src/core.rs":"721de353d3b0b5126bf5b25cfb1f99244702309ce9f9f24cc2ce3c5858228794","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/framing.rs":"45122f0bc44458d8e111466437e784f0d17035309cb5f03d45a5861082168ea1","src/lib.rs":"1075018e9816776af743b31aa491b439bb28a300431cf24a183aa3ad7a1dec08","src/messages.rs":"45ca1c8aee63b991d0160f50f06d280527e7bc28972c28fa35f4f649836cadb0","src/messagestream_unix.rs":"786ea7d2d2993c21987d34c0617abd78dbaa57079de68ea3ebbf5611a052f60b","src/messagestream_win.rs":"f5b2a0e22f56a14af24a76a4c13a1d6b066fbea347132a5413bee0bd2b757753","src/msg.rs":"f5353e942f7818742190541e568685d6b4d6200b55bfc60e46ee3db05f802436","src/rpc/client/mod.rs":"04e80b689548e7888b34441a7224dfa8cf557b8b4164754daee95a95b76f9aee","src/rpc/client/proxy.rs":"8d9c9b38ecec4ab5ee3b6e4c2d7aea9dbb4f7cf5c25d39a5db0c76aa41008497","src/rpc/driver.rs":"dea4efc844485e98c21f766772422e3a5c9ac153ade32c0ff51287516a05690b","src/rpc/mod.rs":"3b14af0be2b4c7b30a0dab9cca353e092652a16e29002f5aeba24dca45e33d1e","src/rpc/server.rs":"7caf0b2d659783b4c5c9dd9efe4cb9a2e7d5955c0dfda3d2e79581116bb9334b","src/shm.rs":"94dee9454acfb4541b7757fd6763b8ecfe1961bb0da780caf463dc6509ba1d98","src/tokio_named_pipes.rs":"c0d74ab6330ebdec53db12f0f532b60897c37e70345c368f10165d9b31409643","src/tokio_uds_stream.rs":"652ab6c32855e9b57c7edbb6914f6f27c6b8c1cadebf87d4a127f0dc76aada52"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"ed404e8d060f36e64113f17077404320946bf46eff77c30595a193dc846287d8","build.rs":"3f061cf9a989f63a71c693a543d26f7003e8b643c39c23ea555110252a2c39d2","src/async_msg.rs":"27c5c8215bcbe1364947065ac78198bcd4be7fbae0f5e49ea776cb454c5a6d2c","src/cmsg.rs":"97d8fe99ef94f75db9ed26cb4cf6faf9fbbc913cfa4152a8774ff4e76aead620","src/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/codec.rs":"2e0a05968e07617adc6be0cbf04962c952c621e118f0db308eeeed5ccea4dfce","src/core.rs":"721de353d3b0b5126bf5b25cfb1f99244702309ce9f9f24cc2ce3c5858228794","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/framing.rs":"45122f0bc44458d8e111466437e784f0d17035309cb5f03d45a5861082168ea1","src/lib.rs":"1075018e9816776af743b31aa491b439bb28a300431cf24a183aa3ad7a1dec08","src/messages.rs":"45ca1c8aee63b991d0160f50f06d280527e7bc28972c28fa35f4f649836cadb0","src/messagestream_unix.rs":"786ea7d2d2993c21987d34c0617abd78dbaa57079de68ea3ebbf5611a052f60b","src/messagestream_win.rs":"f5b2a0e22f56a14af24a76a4c13a1d6b066fbea347132a5413bee0bd2b757753","src/msg.rs":"f5353e942f7818742190541e568685d6b4d6200b55bfc60e46ee3db05f802436","src/rpc/client/mod.rs":"04e80b689548e7888b34441a7224dfa8cf557b8b4164754daee95a95b76f9aee","src/rpc/client/proxy.rs":"8d9c9b38ecec4ab5ee3b6e4c2d7aea9dbb4f7cf5c25d39a5db0c76aa41008497","src/rpc/driver.rs":"dea4efc844485e98c21f766772422e3a5c9ac153ade32c0ff51287516a05690b","src/rpc/mod.rs":"3b14af0be2b4c7b30a0dab9cca353e092652a16e29002f5aeba24dca45e33d1e","src/rpc/server.rs":"7caf0b2d659783b4c5c9dd9efe4cb9a2e7d5955c0dfda3d2e79581116bb9334b","src/shm.rs":"94dee9454acfb4541b7757fd6763b8ecfe1961bb0da780caf463dc6509ba1d98","src/tokio_named_pipes.rs":"c0d74ab6330ebdec53db12f0f532b60897c37e70345c368f10165d9b31409643","src/tokio_uds_stream.rs":"652ab6c32855e9b57c7edbb6914f6f27c6b8c1cadebf87d4a127f0dc76aada52"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc/Cargo.toml b/third_party/rust/audioipc/Cargo.toml
index 2bcd049d8baee89f3875c850b180f3300c9c0341..20f35c47f91f7f44685a0b1d9d7f3aaa09b6ec78 100644
--- a/third_party/rust/audioipc/Cargo.toml
+++ b/third_party/rust/audioipc/Cargo.toml
@@ -43,7 +43,7 @@ winapi = { version = "0.3.6", features = ["combaseapi", "memoryapi", "objbase"]
 ashmem = "0.1"
 
 [dependencies.error-chain]
-version = "0.11.0"
+version = "0.12.0"
 default-features = false
 
 [build-dependencies]
diff --git a/third_party/rust/audioipc2-client/.cargo-checksum.json b/third_party/rust/audioipc2-client/.cargo-checksum.json
index 6814a50d70b0a9d371940055c5538e7e55e55f53..6c0cbc0c21e9393f0c65963d5f2b180493e28a15 100644
--- a/third_party/rust/audioipc2-client/.cargo-checksum.json
+++ b/third_party/rust/audioipc2-client/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"722e0313d4de90477ae34dbb95ae7eeff27622329c5689bb4ce6bcd2006c6263","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/context.rs":"060680f87d406cef1f6f94cfae991ae59b5f3a13253e15481716a1a4224682ee","src/lib.rs":"c4a6797734489280f6b97dd72c9e51a7bd7be4104592eece3929e29d45cbca4a","src/send_recv.rs":"064a657c845762be1dbcbbfc18b3f8a51582eb540def8d2ceecf200184ad4f7a","src/stream.rs":"a6c07796e6fe704cfa6baf8b904e7ffe874d3c884d44d4ed307e668dec25452b"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"722e0313d4de90477ae34dbb95ae7eeff27622329c5689bb4ce6bcd2006c6263","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/context.rs":"33231853817615e01fd1a0f67f69a176d19119bbebb7dc417e96ed88dd3a8d34","src/lib.rs":"c4a6797734489280f6b97dd72c9e51a7bd7be4104592eece3929e29d45cbca4a","src/send_recv.rs":"064a657c845762be1dbcbbfc18b3f8a51582eb540def8d2ceecf200184ad4f7a","src/stream.rs":"a6c07796e6fe704cfa6baf8b904e7ffe874d3c884d44d4ed307e668dec25452b"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc2-client/src/context.rs b/third_party/rust/audioipc2-client/src/context.rs
index a15880509c99a25069d6ea59adcd8b3d7760f0df..86f9cff2850fca1e375687bc9d4666992421f853 100644
--- a/third_party/rust/audioipc2-client/src/context.rs
+++ b/third_party/rust/audioipc2-client/src/context.rs
@@ -246,13 +246,11 @@ impl ContextOps for ClientContext {
         collection: &DeviceCollectionRef,
     ) -> Result<()> {
         assert_not_in_callback();
-        let v: Vec<ffi::cubeb_device_info> = match send_recv!(self.rpc(),
-                             ContextGetDeviceEnumeration(devtype.bits()) =>
-                             ContextEnumeratedDevices())
-        {
-            Ok(mut v) => v.drain(..).map(|i| i.into()).collect(),
-            Err(e) => return Err(e),
-        };
+        let v: Vec<ffi::cubeb_device_info> = send_recv!(
+            self.rpc(), ContextGetDeviceEnumeration(devtype.bits()) => ContextEnumeratedDevices())?
+        .into_iter()
+        .map(|i| i.into())
+        .collect();
         let mut vs = v.into_boxed_slice();
         let coll = unsafe { &mut *collection.as_ptr() };
         coll.device = vs.as_mut_ptr();
diff --git a/third_party/rust/audioipc2-server/.cargo-checksum.json b/third_party/rust/audioipc2-server/.cargo-checksum.json
index c781d9f62f9bc52ed3ae6d8870a66a860829c9fa..367ea72dc1fcdcbc43fdf6e2f15485e57c7f3257 100644
--- a/third_party/rust/audioipc2-server/.cargo-checksum.json
+++ b/third_party/rust/audioipc2-server/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"7380211888012016521396ca4448b483301ce3b2861b4777ffaa991db34b2f31","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/lib.rs":"06aff4fd1326aeabb16b01f81a6f3c59c1717ebe96285a063724830cdf30303a","src/server.rs":"0e33d5f4b37c07f627f2998616fc1c740267fd711daf66ec2a460b489a8c2b8a"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"b1b8509154c7230cd0dca49d0dcc1aa6cabf1a02e0abbd62d7f25ccd3e301804","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/lib.rs":"06aff4fd1326aeabb16b01f81a6f3c59c1717ebe96285a063724830cdf30303a","src/server.rs":"e675dfbb82b515a027262dd5291186771f81e5c0eb4842200321f81800d6a8dc"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc2-server/Cargo.toml b/third_party/rust/audioipc2-server/Cargo.toml
index 6db1e47973a3c9860a8bd48096545594ea47a0f3..a54d5aa29f9ea4dc7113d088d6b0ab0ec46e7b21 100644
--- a/third_party/rust/audioipc2-server/Cargo.toml
+++ b/third_party/rust/audioipc2-server/Cargo.toml
@@ -17,7 +17,7 @@ log = "0.4"
 slab = "0.4"
 
 [dependencies.error-chain]
-version = "0.11.0"
+version = "0.12.0"
 default-features = false
 
 [dependencies.audio_thread_priority]
diff --git a/third_party/rust/audioipc2-server/src/server.rs b/third_party/rust/audioipc2-server/src/server.rs
index aa7af7e82561b9f8cb5c2d8db91a9eccd5a65860..2c225452329eef87188ed060e4baaab7fb447b98 100644
--- a/third_party/rust/audioipc2-server/src/server.rs
+++ b/third_party/rust/audioipc2-server/src/server.rs
@@ -15,7 +15,7 @@ use audioipc::shm::SharedMem;
 use audioipc::{ipccore, rpccore, sys, PlatformHandle};
 use cubeb_core as cubeb;
 use cubeb_core::ffi;
-use std::convert::From;
+use std::convert::{From, TryInto};
 use std::ffi::CStr;
 use std::mem::size_of;
 use std::os::raw::{c_long, c_void};
@@ -31,7 +31,7 @@ fn error(error: cubeb::Error) -> ClientMessage {
 }
 
 struct CubebDeviceCollectionManager {
-    servers: Mutex<Vec<Rc<RefCell<DeviceCollectionChangeCallback>>>>,
+    servers: Mutex<Vec<(Rc<DeviceCollectionChangeCallback>, cubeb::DeviceType)>>,
 }
 
 impl CubebDeviceCollectionManager {
@@ -42,51 +42,27 @@ impl CubebDeviceCollectionManager {
     }
 
     fn register(
-        &mut self,
+        &self,
         context: &cubeb::Context,
-        server: &Rc<RefCell<DeviceCollectionChangeCallback>>,
+        server: &Rc<DeviceCollectionChangeCallback>,
         devtype: cubeb::DeviceType,
     ) -> cubeb::Result<()> {
-        server.borrow_mut().devtype.insert(devtype);
         let mut servers = self.servers.lock().unwrap();
-        let do_register = servers.is_empty();
-        if !servers.iter().any(|s| Rc::ptr_eq(s, server)) {
-            servers.push(server.clone());
-        }
-        if do_register {
+        if servers.is_empty() {
             self.internal_register(context, true)?;
         }
+        servers.push((server.clone(), devtype));
         Ok(())
     }
 
     fn unregister(
-        &mut self,
+        &self,
         context: &cubeb::Context,
-        server: &Rc<RefCell<DeviceCollectionChangeCallback>>,
+        server: &Rc<DeviceCollectionChangeCallback>,
         devtype: cubeb::DeviceType,
     ) -> cubeb::Result<()> {
-        let do_remove = {
-            server.borrow_mut().devtype.remove(devtype);
-            server.borrow().devtype.is_empty()
-        };
-        let mut servers = self.servers.lock().unwrap();
-        if do_remove {
-            servers.retain(|s| !Rc::ptr_eq(s, server));
-        }
-        if servers.is_empty() {
-            self.internal_register(context, false)?;
-        }
-        Ok(())
-    }
-
-    fn unregister_server(
-        &mut self,
-        context: &cubeb::Context,
-        server: &Rc<RefCell<DeviceCollectionChangeCallback>>,
-    ) -> cubeb::Result<()> {
-        server.borrow_mut().devtype = cubeb::DeviceType::UNKNOWN;
         let mut servers = self.servers.lock().unwrap();
-        servers.retain(|s| !Rc::ptr_eq(s, server));
+        servers.retain(|(s, d)| !Rc::ptr_eq(s, server) || d != &devtype);
         if servers.is_empty() {
             self.internal_register(context, false)?;
         }
@@ -94,11 +70,6 @@ impl CubebDeviceCollectionManager {
     }
 
     fn internal_register(&self, context: &cubeb::Context, enable: bool) -> cubeb::Result<()> {
-        let user_ptr = if enable {
-            self as *const CubebDeviceCollectionManager as *mut c_void
-        } else {
-            std::ptr::null_mut()
-        };
         for &(dir, cb) in &[
             (
                 cubeb::DeviceType::INPUT,
@@ -113,25 +84,22 @@ impl CubebDeviceCollectionManager {
                 context.register_device_collection_changed(
                     dir,
                     if enable { Some(cb) } else { None },
-                    user_ptr,
+                    if enable {
+                        self as *const CubebDeviceCollectionManager as *mut c_void
+                    } else {
+                        std::ptr::null_mut()
+                    },
                 )?;
             }
         }
         Ok(())
     }
 
-    // Warning: this is called from an internal cubeb thread, so we must not mutate unprotected shared state.
     unsafe fn device_collection_changed_callback(&self, device_type: ffi::cubeb_device_type) {
         let servers = self.servers.lock().unwrap();
-        servers.iter().for_each(|server| {
-            if server
-                .borrow()
-                .devtype
-                .contains(cubeb::DeviceType::from_bits_truncate(device_type))
-            {
-                server
-                    .borrow_mut()
-                    .device_collection_changed_callback(device_type)
+        servers.iter().for_each(|(s, d)| {
+            if d.contains(cubeb::DeviceType::from_bits_truncate(device_type)) {
+                s.device_collection_changed_callback(device_type)
             }
         });
     }
@@ -258,8 +226,16 @@ impl ServerStreamCallbacks {
             output.len()
         );
 
-        unsafe {
-            if self.input_frame_size != 0 {
+        if self.input_frame_size != 0 {
+            if input.len() > self.shm.get_size() {
+                debug!(
+                    "bad input size: input={} shm={}",
+                    input.len(),
+                    self.shm.get_size()
+                );
+                return cubeb::ffi::CUBEB_ERROR.try_into().unwrap();
+            }
+            unsafe {
                 self.shm
                     .get_mut_slice(input.len())
                     .unwrap()
@@ -267,6 +243,15 @@ impl ServerStreamCallbacks {
             }
         }
 
+        if self.output_frame_size != 0 && output.len() > self.shm.get_size() {
+            debug!(
+                "bad output size: output={} shm={}",
+                output.len(),
+                self.shm.get_size()
+            );
+            return cubeb::ffi::CUBEB_ERROR.try_into().unwrap();
+        }
+
         let r = self
             .data_callback_rpc
             .call(CallbackReq::Data {
@@ -278,13 +263,10 @@ impl ServerStreamCallbacks {
 
         match r {
             Ok(CallbackResp::Data(frames)) => {
-                if frames >= 0 {
+                if frames >= 0 && self.output_frame_size != 0 {
                     let nbytes = frames as usize * self.output_frame_size as usize;
-                    trace!("Reslice output to {}", nbytes);
                     unsafe {
-                        if self.output_frame_size != 0 {
-                            output[..nbytes].copy_from_slice(self.shm.get_slice(nbytes).unwrap());
-                        }
+                        output[..nbytes].copy_from_slice(self.shm.get_slice(nbytes).unwrap());
                     }
                 }
                 frames
@@ -357,11 +339,10 @@ impl Drop for ServerStream {
 
 struct DeviceCollectionChangeCallback {
     rpc: rpccore::Proxy<DeviceCollectionReq, DeviceCollectionResp>,
-    devtype: cubeb::DeviceType,
 }
 
 impl DeviceCollectionChangeCallback {
-    fn device_collection_changed_callback(&mut self, device_type: ffi::cubeb_device_type) {
+    fn device_collection_changed_callback(&self, device_type: ffi::cubeb_device_type) {
         // TODO: Assert device_type is in devtype.
         debug!(
             "Sending device collection ({:?}) changed event",
@@ -379,7 +360,7 @@ pub struct CubebServer {
     device_collection_thread: ipccore::EventLoopHandle,
     streams: slab::Slab<ServerStream>,
     remote_pid: Option<u32>,
-    device_collection_change_callbacks: Option<Rc<RefCell<DeviceCollectionChangeCallback>>>,
+    device_collection_change_callbacks: Option<Rc<DeviceCollectionChangeCallback>>,
     devidmap: DevIdMap,
     shm_area_size: usize,
 }
@@ -395,9 +376,13 @@ impl Drop for CubebServer {
                     context: Ok(context),
                 }) = state.as_mut()
                 {
-                    let r = manager.unregister_server(context, device_collection_change_callbacks);
+                    let r = manager.unregister(
+                        context,
+                        device_collection_change_callbacks,
+                        cubeb::DeviceType::all(),
+                    );
                     if r.is_err() {
-                        debug!("CubebServer: unregister_server failed: {:?}", r);
+                        debug!("CubebServer: unregister failed: {:?}", r);
                     }
                 }
             })
@@ -632,10 +617,7 @@ impl CubebServer {
                 };
 
                 self.device_collection_change_callbacks =
-                    Some(Rc::new(RefCell::new(DeviceCollectionChangeCallback {
-                        rpc,
-                        devtype: cubeb::DeviceType::empty(),
-                    })));
+                    Some(Rc::new(DeviceCollectionChangeCallback { rpc }));
                 let fd = RegisterDeviceCollectionChanged {
                     platform_handle: SerializableHandle::new(client_pipe, self.remote_pid.unwrap()),
                 };
diff --git a/third_party/rust/audioipc2/.cargo-checksum.json b/third_party/rust/audioipc2/.cargo-checksum.json
index 5720115ccb6d14c72017a95ea80f0c53faf38300..c49f348ea4140b9b70701ada9463a3553d28cc7f 100644
--- a/third_party/rust/audioipc2/.cargo-checksum.json
+++ b/third_party/rust/audioipc2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"b22cdc26a865f1a40afdfda1c3782c48dbe59bdeb4c4dda1468d0329af9b935a","benches/serialization.rs":"d56855d868dab6aa22c8b03a61084535351b76c94b68d8b1d20764e352fe473f","build.rs":"3f061cf9a989f63a71c693a543d26f7003e8b643c39c23ea555110252a2c39d2","src/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/codec.rs":"58351c01b0414ec15f29d7dab4693508acfd4d7ca9df575e0eafffe4fe621e8e","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/ipccore.rs":"74e91855ebfae112ecf93fd591987d7a9a7a36a7e19b364960e34455016e892d","src/lib.rs":"84d4b3db37309ca6dd735a59270a787049028d048458af514ef9b3aaf6a2dd58","src/messages.rs":"d5db81981851fec20c6b9ff86a97b360b6e8c4fba2106f5afa286cbada303a72","src/rpccore.rs":"9fa24cb6d487b436382e35f82d0809ad2b315ce049ebaa767b4f88d3d5637f2e","src/shm.rs":"0036b686b4b53171a30e46b7c44335f89db13d37fa2ef24af1ee5a8c920e79e6","src/sys/mod.rs":"da4412ee630e53a0d3a79d9e18953280818bd58ed3fb3c6abedeeb8a092d3dfc","src/sys/unix/cmsg.rs":"e10e26cdfa92035ccb300dc4f2aef05eb1935833045cffb6b1107acc55889c8e","src/sys/unix/mod.rs":"3a2807c7b87ab5230d73fafd2f6417f6647e6d8ffdad7965d1d71bf511da0bcc","src/sys/unix/msg.rs":"d29d3974c145df8b1b931222f62aa64be0ec165b578f31b8f98555fa4d052b01","src/sys/windows/mod.rs":"50af90f17d9b61045ac009e0f53077f9a645c72c214c400b116c4eca2adce0d7"},"package":null}
\ No newline at end of file
+{"files":{"Cargo.toml":"d89d3cd7345174fef6ac44c488c3ec3fc34bac61af8c1fa60561eae5cbc2608a","benches/serialization.rs":"d56855d868dab6aa22c8b03a61084535351b76c94b68d8b1d20764e352fe473f","build.rs":"3f061cf9a989f63a71c693a543d26f7003e8b643c39c23ea555110252a2c39d2","src/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/codec.rs":"58351c01b0414ec15f29d7dab4693508acfd4d7ca9df575e0eafffe4fe621e8e","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/ipccore.rs":"74e91855ebfae112ecf93fd591987d7a9a7a36a7e19b364960e34455016e892d","src/lib.rs":"84d4b3db37309ca6dd735a59270a787049028d048458af514ef9b3aaf6a2dd58","src/messages.rs":"d5db81981851fec20c6b9ff86a97b360b6e8c4fba2106f5afa286cbada303a72","src/rpccore.rs":"9fa24cb6d487b436382e35f82d0809ad2b315ce049ebaa767b4f88d3d5637f2e","src/shm.rs":"1d88f19606899e3e477865d6b84bbe3e272f51618a1c2d57b6dab03a4787cde3","src/sys/mod.rs":"da4412ee630e53a0d3a79d9e18953280818bd58ed3fb3c6abedeeb8a092d3dfc","src/sys/unix/cmsg.rs":"e10e26cdfa92035ccb300dc4f2aef05eb1935833045cffb6b1107acc55889c8e","src/sys/unix/mod.rs":"3a2807c7b87ab5230d73fafd2f6417f6647e6d8ffdad7965d1d71bf511da0bcc","src/sys/unix/msg.rs":"d29d3974c145df8b1b931222f62aa64be0ec165b578f31b8f98555fa4d052b01","src/sys/windows/mod.rs":"50af90f17d9b61045ac009e0f53077f9a645c72c214c400b116c4eca2adce0d7"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/audioipc2/Cargo.toml b/third_party/rust/audioipc2/Cargo.toml
index c55bda1e7420d79012d1ddb6337b81dfdc004892..bd098b02b34471df78d3afd081886b05dbaa1138 100644
--- a/third_party/rust/audioipc2/Cargo.toml
+++ b/third_party/rust/audioipc2/Cargo.toml
@@ -39,7 +39,7 @@ winapi = { version = "0.3", features = ["combaseapi", "memoryapi", "objbase"] }
 ashmem = "0.1.2"
 
 [dependencies.error-chain]
-version = "0.11.0"
+version = "0.12.0"
 default-features = false
 
 [build-dependencies]
diff --git a/third_party/rust/audioipc2/src/shm.rs b/third_party/rust/audioipc2/src/shm.rs
index e5216a234356099c7830b3ac6c08b60c981d20bb..2aaa92ef36b6e80322da3a9d2173e0f0073ce7ed 100644
--- a/third_party/rust/audioipc2/src/shm.rs
+++ b/third_party/rust/audioipc2/src/shm.rs
@@ -235,6 +235,10 @@ mod unix {
         pub unsafe fn get_mut_slice(&mut self, size: usize) -> Result<&mut [u8]> {
             self.view.get_mut_slice(size)
         }
+
+        pub fn get_size(&self) -> usize {
+            self.view.size
+        }
     }
 }
 
@@ -322,5 +326,9 @@ mod windows {
         pub unsafe fn get_mut_slice(&mut self, size: usize) -> Result<&mut [u8]> {
             self.view.get_mut_slice(size)
         }
+
+        pub fn get_size(&self) -> usize {
+            self.view.size
+        }
     }
 }
diff --git a/third_party/rust/error-chain/.cargo-checksum.json b/third_party/rust/error-chain/.cargo-checksum.json
index 1d3eb9bec5a1b0a27d1eea8eb9725419d9cc3762..25299cf4be792ba449f7b9141d029e1ca4fe7d2d 100644
--- a/third_party/rust/error-chain/.cargo-checksum.json
+++ b/third_party/rust/error-chain/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"010cba4f5cdf9607eb744e83a666a3642d6c1aae5d467c67978e97a7f7e86bd8","Cargo.toml":"d8d10d260671883629d2b7e6c5daca5eb2b49b8b1c88345e530462ea1a2e6913","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c43864d39cedab9a1b2aa3d5e480cb58f74cac0b07756670a30c683ce34976a1","README.md":"d63912fd7a5a1a2b1d21edde3cee58cbe422c29b9fcdcc7b8ba2264bf15825b5","examples/all.rs":"cf8422ea6fdb61dbe9ddbb2db51daba48768e3b1d81c5f9e454371c258954cfb","examples/chain_err.rs":"fbb6f90397d5e621e4982d224caf3d419a3c1aaa50f07e5c9c617a9352cfb81f","examples/doc.rs":"790ad6877c91e4e5b2d78829c58702100dcccf3eac2279940257691420cdff03","examples/quickstart.rs":"ca471b3c310d40e5f5dc07db2bfbfcedb71dfc1e25021a6383a9810b24e8fc40","examples/size.rs":"a67ba47b254fb899cb0ecf809e95f75649bb0e401feece9485a2064e223602ab","src/bin/has_backtrace.rs":"eedf028ff206938760a53e91d13534b6ad6780b2b6635f405b7896125484a869","src/error_chain.rs":"5fc674d965746f3ea1a6ea65f82352c40b83439004480bf5a338748a90e476cc","src/example_generated.rs":"95a1e191917740885286f199186674ed575d807077b57dffe6388a4fe2e1ba98","src/impl_error_chain_kind.rs":"538c6f7a2382d555f809c4d7f33e739dff7aa75b2fb3c1629ca2afaa38ff4279","src/lib.rs":"0adc37e316f45d57d56d76245c76942d2a894643c4d2da744639d33c3cd99099","src/quick_main.rs":"472f0b90b11d346cbceec5a95da78fabda0fb55e7e019dc62ac8ff0c206841ea","tests/quick_main.rs":"39a1113cc0d30e5b265e4139cda36f910f8c534a4409e99a9a506a0e88e58f19","tests/tests.rs":"2b76317571651999c294c639088ec7d764c27721d802ea6bc624cfdf31619623"},"package":"ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"ef6a507058abf31f0e9ca96757e28b02a901ae79e762a3bc7fcf8d1e94fc2d44","Cargo.lock":"f0ff8421e2cf5c319f8201727880716565c3e78ee01c2914f2272cbb6d5f8e32","Cargo.toml":"2a75162596294a04af11f94219ec36c01eee6702027a09918df871fad233e9c7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c43864d39cedab9a1b2aa3d5e480cb58f74cac0b07756670a30c683ce34976a1","README.md":"9fe679f0803f83d65a5b6a26d11305fe042b9ff59494cba31a5904e643240e8e","build.rs":"a1424a03c2df37c5784e8837ce025ad7c2a9efe2e603c80efd3f7ccfbe6b8f07","examples/all.rs":"6f073ea0e3db541a4eefb41436fc03a121a1f932fd6a2798b485a72d64bd1a3c","examples/chain_err.rs":"9a4cfc00808dfde57c97f65969d4ed5a48335b1880c1e2507b71fd9b711bdbae","examples/doc.rs":"426789ff58b2f8792e867d5d85fdb74507cda160285f0130f50d7c4cfff4a51c","examples/has_backtrace.rs":"eedf028ff206938760a53e91d13534b6ad6780b2b6635f405b7896125484a869","examples/quickstart.rs":"80a744c7d309662409b4db255ddcd714e63b2e82a1f0ff00e21525289bbdfe48","examples/size.rs":"d778532f17d9d55e3eb421d920b1cf09b4284d160fffe7c5522258527c8d284c","src/backtrace.rs":"bf70954c483e54fc13f5235efca08f21a02764f34fccdc1a657e66f3632f6f59","src/error_chain.rs":"cb315489643af2b7da7868239b0f1f0e3e6cd3e900030b38617eeddd30e757fc","src/example_generated.rs":"b0742d8df91948a81db01a9b455e0bbe9b211b9c2644a7f10d59f0e099083231","src/impl_error_chain_kind.rs":"ed27688a857e15f4f120769bae892c0280f96e4e082b42ebb2ba1af02f8875ee","src/lib.rs":"cd469e2f18653fc1e6541d82a566a94d8b5769a2e5c6abf3fcdd967eab22246f","src/quick_main.rs":"f77f74104cff1825d9885be1708b5128508312ed5ac92c806fdafa0336f47ead","tests/quick_main.rs":"39a1113cc0d30e5b265e4139cda36f910f8c534a4409e99a9a506a0e88e58f19","tests/tests.rs":"3b80f2c8d45d06dea2ef1375579e63e2fc904ee8c22b1abf285f062b3c1ce271"},"package":"2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"}
\ No newline at end of file
diff --git a/third_party/rust/error-chain/CHANGELOG.md b/third_party/rust/error-chain/CHANGELOG.md
index ed0f12e3a1bc6f6d758903bdd59ca21903bef3f8..bd82afc3d51ebdfe0de09e2bf1de50814e671ab3 100644
--- a/third_party/rust/error-chain/CHANGELOG.md
+++ b/third_party/rust/error-chain/CHANGELOG.md
@@ -1,4 +1,20 @@
-# Unreleased
+# 0.12.4
+- [executable bits to support build platform linters](https://github.com/rust-lang-nursery/error-chain/pull/289)
+
+# 0.12.2
+- [allow `Error::description` to be used for rust below 1.42](https://github.com/rust-lang-nursery/error-chain/pull/285)
+- [Improvements to has_backtrace_depending_on_env](https://github.com/rust-lang-nursery/error-chain/pull/277)
+- Backtrace support now requires rust 1.32.0
+
+# 0.12.1
+
+- [`std::error::Error::cause` deprecation update](https://github.com/rust-lang-nursery/error-chain/pull/255)
+- [Macro invocations use 2018 style](https://github.com/rust-lang-nursery/error-chain/pull/253)
+
+# 0.12.0
+
+- [Remove `impl Deref<Kind> for Error`](https://github.com/rust-lang-nursery/error-chain/pull/192)
+- [Fix warning](https://github.com/rust-lang-nursery/error-chain/pull/247)
 
 # 0.11.0
 
diff --git a/third_party/rust/error-chain/Cargo.lock b/third_party/rust/error-chain/Cargo.lock
new file mode 100644
index 0000000000000000000000000000000000000000..9453307464cfa2ed87c60bfb91d5566aace1d930
--- /dev/null
+++ b/third_party/rust/error-chain/Cargo.lock
@@ -0,0 +1,67 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "addr2line"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
+dependencies = [
+ "addr2line",
+ "cfg-if",
+ "libc",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "error-chain"
+version = "0.12.4"
+dependencies = [
+ "backtrace",
+ "version_check",
+]
+
+[[package]]
+name = "gimli"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
+
+[[package]]
+name = "libc"
+version = "0.2.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
+
+[[package]]
+name = "object"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
+
+[[package]]
+name = "version_check"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
diff --git a/third_party/rust/error-chain/Cargo.toml b/third_party/rust/error-chain/Cargo.toml
index 6c4e0e4986bd742a5bb99edec2aaee680ae16567..55ed9ac659294672dbf6f1276e294b5fe33b285e 100644
--- a/third_party/rust/error-chain/Cargo.toml
+++ b/third_party/rust/error-chain/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,8 +12,8 @@
 
 [package]
 name = "error-chain"
-version = "0.11.0"
-authors = ["Brian Anderson <banderson@mozilla.com>", "Paul Colomiets <paul@colomiets.name>", "Colin Kiegel <kiegel@gmx.de>", "Yamakaky <yamakaky@yamaworld.fr>"]
+version = "0.12.4"
+authors = ["Brian Anderson <banderson@mozilla.com>", "Paul Colomiets <paul@colomiets.name>", "Colin Kiegel <kiegel@gmx.de>", "Yamakaky <yamakaky@yamaworld.fr>", "Andrew Gauger <andygauge@gmail.com>"]
 description = "Yet another error boilerplate library."
 documentation = "https://docs.rs/error-chain"
 readme = "README.md"
@@ -22,11 +22,11 @@ categories = ["rust-patterns"]
 license = "MIT/Apache-2.0"
 repository = "https://github.com/rust-lang-nursery/error-chain"
 [dependencies.backtrace]
-version = "0.3"
+version = "0.3.3"
 optional = true
+[build-dependencies.version_check]
+version = "0.9"
 
 [features]
-example_generated = []
 default = ["backtrace", "example_generated"]
-[badges.travis-ci]
-repository = "rust-lang-nursery/error-chain"
+example_generated = []
diff --git a/third_party/rust/error-chain/README.md b/third_party/rust/error-chain/README.md
index 51e50533ed718373382480ed5532d4e5d8adb362..b87224d18da730b1443a87da34a866d480ab9d37 100644
--- a/third_party/rust/error-chain/README.md
+++ b/third_party/rust/error-chain/README.md
@@ -1,8 +1,8 @@
 # error-chain - Consistent error handling for Rust
 
-[![Build Status](https://api.travis-ci.org/rust-lang-nursery/error-chain.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/error-chain)
+[![Build Status](https://travis-ci.com/rust-lang-nursery/error-chain.svg?branch=master)](https://travis-ci.com/rust-lang-nursery/error-chain)
 [![Latest Version](https://img.shields.io/crates/v/error-chain.svg)](https://crates.io/crates/error-chain)
-[![License](https://img.shields.io/github/license/rust-lang-nursery/error-chain.svg)](https://github.com/rust-lang-nursery/error-chain)
+[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-green.svg)](https://github.com/rust-lang-nursery/error-chain)
 
 `error-chain` makes it easy to take full advantage of Rust's error
 handling features without the overhead of maintaining boilerplate
diff --git a/third_party/rust/error-chain/build.rs b/third_party/rust/error-chain/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..612f2091de4b56e8949465b697c2a0a8f900c854
--- /dev/null
+++ b/third_party/rust/error-chain/build.rs
@@ -0,0 +1,21 @@
+extern crate version_check;
+
+use std::env;
+use version_check::is_min_version;
+
+fn main() {
+    // Switch on for versions that have Error::source
+    // As introduced by https://github.com/rust-lang/rust/pull/53533
+    if is_min_version("1.30").unwrap_or(false) {
+        println!("cargo:rustc-cfg=has_error_source");
+    }
+
+    if is_min_version("1.42").unwrap_or(false) {
+        println!("cargo:rustc-cfg=has_error_description_deprecated");
+    }
+
+    // So we can get the build profile for has_backtrace_depending_on_env test
+    if let Ok(profile) = env::var("PROFILE") {
+        println!("cargo:rustc-cfg=build={:?}", profile);
+    }
+}
diff --git a/third_party/rust/error-chain/examples/all.rs b/third_party/rust/error-chain/examples/all.rs
index ccc3ab7032bcebd8ef2410e6bb51e721f1b8ba11..840ca95e27b2af3d5850841fc3a6196fe1768f9c 100644
--- a/third_party/rust/error-chain/examples/all.rs
+++ b/third_party/rust/error-chain/examples/all.rs
@@ -2,12 +2,12 @@
 extern crate error_chain;
 
 pub mod inner {
-    error_chain!{}
+    error_chain! {}
 }
 
 #[cfg(feature = "a_feature")]
 pub mod feature {
-    error_chain!{}
+    error_chain! {}
 }
 
 error_chain! {
diff --git a/third_party/rust/error-chain/examples/chain_err.rs b/third_party/rust/error-chain/examples/chain_err.rs
index bd8effdaf6b97ae5b23b611d7b032c76b20a1ce1..c70a25dd60a2b40f8662c86d2eb0183da83d6aeb 100644
--- a/third_party/rust/error-chain/examples/chain_err.rs
+++ b/third_party/rust/error-chain/examples/chain_err.rs
@@ -7,8 +7,8 @@ extern crate error_chain;
 use std::fs::File;
 
 mod errors {
-    use std::io;
     use super::LaunchStage;
+    use std::io;
 
     error_chain! {
         foreign_links {
@@ -54,11 +54,9 @@ fn load_config(rel_path: &str) -> Result<()> {
 /// Launch the service.
 fn launch(rel_path: &str) -> Result<()> {
     load_config(rel_path).map_err(|e| match e {
-                                      e @ Error(ErrorKind::ConfigLoad(_), _) => {
-                                          e.chain_err(|| LaunchStage::ConfigLoad)
-                                      }
-                                      e => e.chain_err(|| "Unknown failure"),
-                                  })
+        e @ Error(ErrorKind::ConfigLoad(_), _) => e.chain_err(|| LaunchStage::ConfigLoad),
+        e => e.chain_err(|| "Unknown failure"),
+    })
 }
 
 fn main() {
diff --git a/third_party/rust/error-chain/examples/doc.rs b/third_party/rust/error-chain/examples/doc.rs
index 999ac9cef0ae374115f988872218e10e62775cdb..68f57d788461789e8b3bffac872e0c7b4ca995c5 100644
--- a/third_party/rust/error-chain/examples/doc.rs
+++ b/third_party/rust/error-chain/examples/doc.rs
@@ -7,7 +7,7 @@ extern crate error_chain;
 
 /// Inner module.
 pub mod inner {
-    error_chain!{}
+    error_chain! {}
 }
 
 error_chain! {
diff --git a/third_party/rust/error-chain/src/bin/has_backtrace.rs b/third_party/rust/error-chain/examples/has_backtrace.rs
similarity index 100%
rename from third_party/rust/error-chain/src/bin/has_backtrace.rs
rename to third_party/rust/error-chain/examples/has_backtrace.rs
diff --git a/third_party/rust/error-chain/examples/quickstart.rs b/third_party/rust/error-chain/examples/quickstart.rs
index 2e3e2b5d3945cada1198cd5cd9519ab53858e9db..e410a62b8a71efefd8069d6df67a88ab9dd02b0c 100644
--- a/third_party/rust/error-chain/examples/quickstart.rs
+++ b/third_party/rust/error-chain/examples/quickstart.rs
@@ -14,7 +14,7 @@ extern crate error_chain;
 // `error_chain!` creates.
 mod errors {
     // Create the Error, ErrorKind, ResultExt, and Result types
-    error_chain!{}
+    error_chain! {}
 }
 
 // This only gives access within this module. Make this `pub use errors::*;`
@@ -51,8 +51,8 @@ fn main() {
 #[allow(dead_code)]
 fn alternative_main() {
     if let Err(ref e) = run() {
-        use std::io::Write;
-        use error_chain::ChainedError; // trait which holds `display_chain`
+        use error_chain::ChainedError;
+        use std::io::Write; // trait which holds `display_chain`
         let stderr = &mut ::std::io::stderr();
         let errmsg = "Error writing to stderr";
 
@@ -65,7 +65,6 @@ fn alternative_main() {
 // set the `RUST_BACKTRACE` env variable to see a backtrace.
 // quick_main!(run);
 
-
 // Most functions will return the `Result` type, imported from the
 // `errors` module. It is a typedef of the standard `Result` type
 // for which the error type is always our own `Error`.
@@ -73,8 +72,7 @@ fn run() -> Result<()> {
     use std::fs::File;
 
     // This operation will fail
-    File::open("tretrete")
-        .chain_err(|| "unable to open tretrete file")?;
+    File::open("tretrete").chain_err(|| "unable to open tretrete file")?;
 
     Ok(())
 }
diff --git a/third_party/rust/error-chain/examples/size.rs b/third_party/rust/error-chain/examples/size.rs
index ae360d66e974ebb7a35bb557f4acc8f2ed05595e..3e180684e812c40f973e060a6a1f931f8646ab86 100644
--- a/third_party/rust/error-chain/examples/size.rs
+++ b/third_party/rust/error-chain/examples/size.rs
@@ -21,18 +21,10 @@ fn main() {
     println!("      ErrorKind::Msg: {}", size_of_val(&msg));
     println!("        String: {}", size_of::<String>());
     println!("    State: {}", size_of::<error_chain::State>());
-    #[cfg(feature = "backtrace")]
-    {
-        let state = error_chain::State {
-            next_error: None,
-            backtrace: None,
-        };
-        println!("      State.next_error: {}", size_of_val(&state.next_error));
-        println!("      State.backtrace: {}", size_of_val(&state.backtrace));
-    }
-    #[cfg(not(feature = "backtrace"))]
-    {
-        let state = error_chain::State { next_error: None };
-        println!("      State.next_error: {}", size_of_val(&state.next_error));
-    }
+    let state = error_chain::State {
+        next_error: None,
+        backtrace: error_chain::InternalBacktrace::new(),
+    };
+    println!("      State.next_error: {}", size_of_val(&state.next_error));
+    println!("      State.backtrace: {}", size_of_val(&state.backtrace));
 }
diff --git a/third_party/rust/error-chain/src/backtrace.rs b/third_party/rust/error-chain/src/backtrace.rs
new file mode 100644
index 0000000000000000000000000000000000000000..14be75ce1ba430b4b83f52218ab86ceca40ca541
--- /dev/null
+++ b/third_party/rust/error-chain/src/backtrace.rs
@@ -0,0 +1,111 @@
+pub use self::imp::{Backtrace, InternalBacktrace};
+
+#[cfg(feature = "backtrace")]
+mod imp {
+    extern crate backtrace;
+
+    use std::cell::UnsafeCell;
+    use std::env;
+    use std::fmt;
+    use std::sync::atomic::{AtomicUsize, Ordering};
+    use std::sync::{Arc, Mutex};
+
+    /// Internal representation of a backtrace
+    #[doc(hidden)]
+    #[derive(Clone)]
+    pub struct InternalBacktrace {
+        backtrace: Option<Arc<MaybeResolved>>,
+    }
+
+    struct MaybeResolved {
+        resolved: Mutex<bool>,
+        backtrace: UnsafeCell<Backtrace>,
+    }
+
+    unsafe impl Send for MaybeResolved {}
+    unsafe impl Sync for MaybeResolved {}
+
+    pub use self::backtrace::Backtrace;
+
+    impl InternalBacktrace {
+        /// Returns a backtrace of the current call stack if `RUST_BACKTRACE`
+        /// is set to anything but ``0``, and `None` otherwise.  This is used
+        /// in the generated error implementations.
+        #[doc(hidden)]
+        pub fn new() -> InternalBacktrace {
+            static ENABLED: AtomicUsize = AtomicUsize::new(0);
+
+            match ENABLED.load(Ordering::SeqCst) {
+                0 => {
+                    let enabled = match env::var_os("RUST_BACKTRACE") {
+                        Some(ref val) if val != "0" => true,
+                        _ => false,
+                    };
+                    ENABLED.store(enabled as usize + 1, Ordering::SeqCst);
+                    if !enabled {
+                        return InternalBacktrace { backtrace: None };
+                    }
+                }
+                1 => return InternalBacktrace { backtrace: None },
+                _ => {}
+            }
+
+            InternalBacktrace {
+                backtrace: Some(Arc::new(MaybeResolved {
+                    resolved: Mutex::new(false),
+                    backtrace: UnsafeCell::new(Backtrace::new_unresolved()),
+                })),
+            }
+        }
+
+        /// Acquire the internal backtrace
+        #[doc(hidden)]
+        pub fn as_backtrace(&self) -> Option<&Backtrace> {
+            let bt = match self.backtrace {
+                Some(ref bt) => bt,
+                None => return None,
+            };
+            let mut resolved = bt.resolved.lock().unwrap();
+            unsafe {
+                if !*resolved {
+                    (*bt.backtrace.get()).resolve();
+                    *resolved = true;
+                }
+                Some(&*bt.backtrace.get())
+            }
+        }
+    }
+
+    impl fmt::Debug for InternalBacktrace {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            f.debug_struct("InternalBacktrace")
+                .field("backtrace", &self.as_backtrace())
+                .finish()
+        }
+    }
+}
+
+#[cfg(not(feature = "backtrace"))]
+mod imp {
+    /// Dummy type used when the `backtrace` feature is disabled.
+    pub type Backtrace = ();
+
+    /// Internal representation of a backtrace
+    #[doc(hidden)]
+    #[derive(Clone, Debug)]
+    pub struct InternalBacktrace {}
+
+    impl InternalBacktrace {
+        /// Returns a new backtrace
+        #[doc(hidden)]
+        pub fn new() -> InternalBacktrace {
+            InternalBacktrace {}
+        }
+
+        /// Returns the internal backtrace
+        #[doc(hidden)]
+        pub fn as_backtrace(&self) -> Option<&Backtrace> {
+            None
+        }
+    }
+}
diff --git a/third_party/rust/error-chain/src/error_chain.rs b/third_party/rust/error-chain/src/error_chain.rs
index cbd42cd67eaf6e58bf09a230b614923eef9e75b3..8382709621ea78ad6163f1c567c46e1578975d0d 100644
--- a/third_party/rust/error-chain/src/error_chain.rs
+++ b/third_party/rust/error-chain/src/error_chain.rs
@@ -1,6 +1,95 @@
-/// Prefer to use `error_chain` instead of this macro.
 #[doc(hidden)]
 #[macro_export]
+#[cfg(not(has_error_source))]
+macro_rules! impl_error_chain_cause_or_source {
+    (
+        types {
+            $error_kind_name:ident
+        }
+
+        foreign_links {
+            $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
+               $( #[$meta_foreign_links:meta] )*; )*
+        }
+    ) => {
+        #[allow(unknown_lints, renamed_and_removed_lints)]
+        #[allow(unused_doc_comment, unused_doc_comments)]
+        fn cause(&self) -> Option<&::std::error::Error> {
+            match self.1.next_error {
+                Some(ref c) => Some(&**c),
+                None => {
+                    match self.0 {
+                        $(
+                            $(#[$meta_foreign_links])*
+                            $error_kind_name::$foreign_link_variant(ref foreign_err) => {
+                                foreign_err.cause()
+                            }
+                        ) *
+                        _ => None
+                    }
+                }
+            }
+        }
+    };
+}
+
+#[cfg(has_error_source)]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_error_chain_cause_or_source {
+    (
+        types {
+             $error_kind_name:ident
+        }
+
+        foreign_links {
+            $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
+               $( #[$meta_foreign_links:meta] )*; )*
+        }
+    ) => {
+            #[allow(unknown_lints, renamed_and_removed_lints, bare_trait_objects)]
+            #[allow(unused_doc_comment, unused_doc_comments)]
+            fn source(&self) -> Option<&(std::error::Error + 'static)> {
+                match self.1.next_error {
+                    Some(ref c) => Some(&**c),
+                    None => {
+                        match self.0 {
+                        $(
+                            $(#[$meta_foreign_links])*
+                            $error_kind_name::$foreign_link_variant(ref foreign_err) => {
+                                foreign_err.source()
+                            }
+                        ) *
+                            _ => None
+                        }
+                    }
+                }
+            }
+        };
+}
+
+/// Conditional usage of deprecated Error::description
+#[doc(hidden)]
+#[cfg(has_error_description_deprecated)]
+#[macro_export(local_inner_macros)]
+macro_rules! call_to_deprecated_description {
+    ($e:ident) => {
+        ""
+    };
+}
+
+#[doc(hidden)]
+#[cfg(not(has_error_description_deprecated))]
+#[macro_export(local_inner_macros)]
+macro_rules! call_to_deprecated_description {
+    ($e:ident) => {
+        ::std::error::Error::description($e)
+    };
+}
+
+/// Prefer to use `error_chain` instead of this macro.
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
 macro_rules! impl_error_chain_processed {
     // Default values for `types`.
     (
@@ -33,13 +122,68 @@ macro_rules! impl_error_chain_processed {
         #[allow(unused)]
         pub type $result_name<T> = ::std::result::Result<T, $error_name>;
     };
-    // Without `Result` wrapper.
+
+    // With `Msg` variant.
+    (
+        types {
+            $error_name:ident, $error_kind_name:ident, $($types:tt)*
+        }
+        links $links:tt
+        foreign_links $foreign_links:tt
+        errors { $($errors:tt)* }
+    ) => {
+        impl_error_chain_processed! {
+            types {
+                $error_name, $error_kind_name, $($types)*
+            }
+            skip_msg_variant
+            links $links
+            foreign_links $foreign_links
+            errors {
+                /// A convenient variant for String.
+                Msg(s: String) {
+                    description(&s)
+                    display("{}", s)
+                }
+
+                $($errors)*
+            }
+        }
+
+        impl<'a> From<&'a str> for $error_kind_name {
+            fn from(s: &'a str) -> Self {
+                $error_kind_name::Msg(s.into())
+            }
+        }
+
+        impl From<String> for $error_kind_name {
+            fn from(s: String) -> Self {
+                $error_kind_name::Msg(s)
+            }
+        }
+
+        impl<'a> From<&'a str> for $error_name {
+            fn from(s: &'a str) -> Self {
+                Self::from_kind(s.into())
+            }
+        }
+
+        impl From<String> for $error_name {
+            fn from(s: String) -> Self {
+                Self::from_kind(s.into())
+            }
+        }
+    };
+
+    // Without `Result` wrapper or `Msg` variant.
     (
         types {
             $error_name:ident, $error_kind_name:ident,
             $result_ext_name:ident;
         }
 
+        skip_msg_variant
+
         links {
             $( $link_variant:ident ( $link_error_path:path, $link_kind_path:path )
                $( #[$meta_links:meta] )*; ) *
@@ -136,6 +280,7 @@ macro_rules! impl_error_chain_processed {
             }
 
             /// Construct a chained error from another boxed error and a kind, and generates a backtrace
+            #[allow(unknown_lints, bare_trait_objects)]
             pub fn with_boxed_chain<K>(error: Box<::std::error::Error + Send>, kind: K)
                 -> $error_name
                 where K: Into<$error_kind_name>
@@ -166,28 +311,27 @@ macro_rules! impl_error_chain_processed {
                 where F: FnOnce() -> EK, EK: Into<$error_kind_name> {
                 $error_name::with_chain(self, Self::from_kind(error().into()))
             }
+
+            /// A short description of the error.
+            /// This method is identical to [`Error::description()`](https://doc.rust-lang.org/nightly/std/error/trait.Error.html#tymethod.description)
+            pub fn description(&self) -> &str {
+                self.0.description()
+            }
         }
 
         impl ::std::error::Error for $error_name {
+            #[cfg(not(has_error_description_deprecated))]
             fn description(&self) -> &str {
-                self.0.description()
+                self.description()
             }
 
-            #[allow(unknown_lints, unused_doc_comment)]
-            fn cause(&self) -> Option<&::std::error::Error> {
-                match self.1.next_error {
-                    Some(ref c) => Some(&**c),
-                    None => {
-                        match self.0 {
-                            $(
-                                $(#[$meta_foreign_links])*
-                                $error_kind_name::$foreign_link_variant(ref foreign_err) => {
-                                    foreign_err.cause()
-                                }
-                            ) *
-                            _ => None
-                        }
-                    }
+            impl_error_chain_cause_or_source!{
+                types {
+                    $error_kind_name
+                }
+                foreign_links {
+                    $( $foreign_link_variant ( $foreign_link_error_path )
+                    $( #[$meta_foreign_links] )*; )*
                 }
             }
         }
@@ -227,27 +371,6 @@ macro_rules! impl_error_chain_processed {
             }
         }
 
-        impl<'a> From<&'a str> for $error_name {
-            fn from(s: &'a str) -> Self {
-                $error_name::from_kind(s.into())
-            }
-        }
-
-        impl From<String> for $error_name {
-            fn from(s: String) -> Self {
-                $error_name::from_kind(s.into())
-            }
-        }
-
-        impl ::std::ops::Deref for $error_name {
-            type Target = $error_kind_name;
-
-            fn deref(&self) -> &Self::Target {
-                &self.0
-            }
-        }
-
-
         // The ErrorKind type
         // --------------
 
@@ -255,13 +378,6 @@ macro_rules! impl_error_chain_processed {
             /// The kind of an error.
             #[derive(Debug)]
             pub enum $error_kind_name {
-
-                /// A convenient variant for String.
-                Msg(s: String) {
-                    description(&s)
-                    display("{}", s)
-                }
-
                 $(
                     $(#[$meta_links])*
                     $link_variant(e: $link_kind_path) {
@@ -273,7 +389,7 @@ macro_rules! impl_error_chain_processed {
                 $(
                     $(#[$meta_foreign_links])*
                     $foreign_link_variant(err: $foreign_link_error_path) {
-                        description(::std::error::Error::description(err))
+                        description(call_to_deprecated_description!(err))
                         display("{}", err)
                     }
                 ) *
@@ -291,18 +407,6 @@ macro_rules! impl_error_chain_processed {
             }
         ) *
 
-        impl<'a> From<&'a str> for $error_kind_name {
-            fn from(s: &'a str) -> Self {
-                $error_kind_name::Msg(s.to_string())
-            }
-        }
-
-        impl From<String> for $error_kind_name {
-            fn from(s: String) -> Self {
-                $error_kind_name::Msg(s)
-            }
-        }
-
         impl From<$error_name> for $error_kind_name {
             fn from(e: $error_name) -> Self {
                 e.0
@@ -349,51 +453,67 @@ macro_rules! impl_error_chain_processed {
 
 /// Internal macro used for reordering of the fields.
 #[doc(hidden)]
-#[macro_export]
+#[macro_export(local_inner_macros)]
 macro_rules! error_chain_processing {
     (
-        ({}, $b:tt, $c:tt, $d:tt)
+        ({}, $($rest:tt)*)
         types $content:tt
         $( $tail:tt )*
     ) => {
         error_chain_processing! {
-            ($content, $b, $c, $d)
+            ($content, $($rest)*)
             $($tail)*
         }
     };
+
     (
-        ($a:tt, {}, $c:tt, $d:tt)
+        ($a:tt, {}, $($rest:tt)*)
         links $content:tt
         $( $tail:tt )*
     ) => {
         error_chain_processing! {
-            ($a, $content, $c, $d)
+            ($a, $content, $($rest)*)
             $($tail)*
         }
     };
+
     (
-        ($a:tt, $b:tt, {}, $d:tt)
+        ($a:tt, $b:tt, {}, $($rest:tt)*)
         foreign_links $content:tt
         $( $tail:tt )*
     ) => {
         error_chain_processing! {
-            ($a, $b, $content, $d)
+            ($a, $b, $content, $($rest)*)
             $($tail)*
         }
     };
+
     (
-        ($a:tt, $b:tt, $c:tt, {})
+        ($a:tt, $b:tt, $c:tt, {}, $($rest:tt)*)
         errors $content:tt
         $( $tail:tt )*
     ) => {
         error_chain_processing! {
-            ($a, $b, $c, $content)
+            ($a, $b, $c, $content, $($rest)*)
+            $($tail)*
+        }
+    };
+
+    (
+        ($a:tt, $b:tt, $c:tt, $d:tt, {}, $($rest:tt)*)
+        skip_msg_variant
+        $( $tail:tt )*
+    ) => {
+        error_chain_processing! {
+            ($a, $b, $c, $d, {skip_msg_variant}, $($rest)*)
             $($tail)*
         }
     };
-    ( ($a:tt, $b:tt, $c:tt, $d:tt) ) => {
+
+    ( ($a:tt, $b:tt, $c:tt, $d:tt, {$($e:tt)*},) ) => {
         impl_error_chain_processed! {
             types $a
+            $($e)*
             links $b
             foreign_links $c
             errors $d
@@ -402,12 +522,12 @@ macro_rules! error_chain_processing {
 }
 
 /// Macro for generating error types and traits. See crate level documentation for details.
-#[macro_export]
+#[macro_export(local_inner_macros)]
 macro_rules! error_chain {
-    ( $( $block_name:ident { $( $block_content:tt )* } )* ) => {
+    ( $($args:tt)* ) => {
         error_chain_processing! {
-            ({}, {}, {}, {})
-            $($block_name { $( $block_content )* })*
+            ({}, {}, {}, {}, {},)
+            $($args)*
         }
     };
 }
@@ -419,22 +539,22 @@ macro_rules! error_chain {
 /// for more details.
 #[macro_export]
 #[doc(hidden)]
-#[cfg(feature = "backtrace")]
 macro_rules! impl_extract_backtrace {
     ($error_name: ident
      $error_kind_name: ident
      $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
-        #[allow(unknown_lints, unused_doc_comment)]
+        #[allow(unknown_lints, renamed_and_removed_lints, bare_trait_objects)]
+        #[allow(unused_doc_comment, unused_doc_comments)]
         fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
-            -> Option<::std::sync::Arc<$crate::Backtrace>> {
+            -> Option<$crate::InternalBacktrace> {
             if let Some(e) = e.downcast_ref::<$error_name>() {
-                return e.1.backtrace.clone();
+                return Some(e.1.backtrace.clone());
             }
             $(
                 $( #[$meta_links] )*
                 {
                     if let Some(e) = e.downcast_ref::<$link_error_path>() {
-                        return e.1.backtrace.clone();
+                        return Some(e.1.backtrace.clone());
                     }
                 }
             ) *
@@ -442,17 +562,3 @@ macro_rules! impl_extract_backtrace {
         }
     }
 }
-
-/// Macro used to manage the `backtrace` feature.
-///
-/// See
-/// https://www.reddit.com/r/rust/comments/57virt/hey_rustaceans_got_an_easy_question_ask_here/da5r4ti/?context=3
-/// for more details.
-#[macro_export]
-#[doc(hidden)]
-#[cfg(not(feature = "backtrace"))]
-macro_rules! impl_extract_backtrace {
-    ($error_name: ident
-     $error_kind_name: ident
-     $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {}
-}
diff --git a/third_party/rust/error-chain/src/example_generated.rs b/third_party/rust/error-chain/src/example_generated.rs
index 413407cae96937cc94d7e95c070fc6d196a885fa..c0f4d23014ff72936ec2472aa41ae463524d9dc2 100644
--- a/third_party/rust/error-chain/src/example_generated.rs
+++ b/third_party/rust/error-chain/src/example_generated.rs
@@ -21,7 +21,7 @@
 
 /// Another code generated by the macro.
 pub mod inner {
-    error_chain!{}
+    error_chain! {}
 }
 
 error_chain! {
@@ -29,7 +29,7 @@ error_chain! {
         Inner(inner::Error, inner::ErrorKind) #[doc = "Link to another `ErrorChain`."];
     }
     foreign_links {
-        Io(::std::io::Error) #[doc = "Link to a `std::error::Error` type."];
+        Io(::std::io::Error) #[doc = "Link to a `std::io::Error` type."];
     }
     errors {
         #[doc = "A custom error kind."]
diff --git a/third_party/rust/error-chain/src/impl_error_chain_kind.rs b/third_party/rust/error-chain/src/impl_error_chain_kind.rs
index d6c05c8a882b7f713b905d8db626e197a7d0193f..4acf8435b29e9580855481ba9df07685308edef5 100644
--- a/third_party/rust/error-chain/src/impl_error_chain_kind.rs
+++ b/third_party/rust/error-chain/src/impl_error_chain_kind.rs
@@ -1,9 +1,24 @@
-// From https://github.com/tailhook/quick-error
-// Changes:
-//   - replace `impl Error` by `impl Item::description`
-//   - $imeta
+/// From https://github.com/tailhook/quick-error
+/// Changes:
+///   - replace `impl Error` by `impl Item::description`
+///   - $imeta
 
+/// Because of the `#[macro_export(local_inner_macros)]` usage on `impl_error_chain_kind` that macro
+/// will only look inside this crate for macros to invoke. So using `stringify` or `write` from
+/// the standard library will fail. Thus we here create simple wrappers for them that are not
+/// exported as `local_inner_macros`, and thus they can in turn use the standard library macros.
 #[macro_export]
+macro_rules! stringify_internal {
+    ($($t:tt)*) => { stringify!($($t)*) }
+}
+
+/// Macro used interally for output expanding an expression
+#[macro_export]
+macro_rules! write_internal {
+    ($dst:expr, $($arg:tt)*) => (write!($dst, $($arg)*))
+}
+
+#[macro_export(local_inner_macros)]
 #[doc(hidden)]
 macro_rules! impl_error_chain_kind {
     (   $(#[$meta:meta])*
@@ -13,33 +28,7 @@ macro_rules! impl_error_chain_kind {
             items [] buf []
             queue [ $($chunks)* ]);
     };
-    (   $(#[$meta:meta])*
-        enum $name:ident { $($chunks:tt)* }
-    ) => {
-        impl_error_chain_kind!(SORT [enum $name $(#[$meta])* ]
-            items [] buf []
-            queue [ $($chunks)* ]);
-    };
     // Queue is empty, can do the work
-    (SORT [enum $name:ident $( #[$meta:meta] )*]
-        items [$($( #[$imeta:meta] )*
-                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
-                                {$( $ifuncs:tt )*} )* ]
-        buf [ ]
-        queue [ ]
-    ) => {
-        impl_error_chain_kind!(ENUM_DEFINITION [enum $name $( #[$meta] )*]
-            body []
-            queue [$($( #[$imeta] )*
-                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
-        );
-        impl_error_chain_kind!(IMPLEMENTATIONS $name {$(
-           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
-           )*});
-        $(
-            impl_error_chain_kind!(ERROR_CHECK $imode $($ifuncs)*);
-        )*
-    };
     (SORT [pub enum $name:ident $( #[$meta:meta] )*]
         items [$($( #[$imeta:meta] )*
                   => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
@@ -96,8 +85,7 @@ macro_rules! impl_error_chain_kind {
         queue [ #[$qmeta:meta] $( $tail:tt )*]
     ) => {
         impl_error_chain_kind!(SORT [$( $def )*]
-            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
-                     $(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
+            enum [$(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
             items [$($( #[$imeta:meta] )*
                       => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
                      $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
@@ -114,7 +102,7 @@ macro_rules! impl_error_chain_kind {
     ) => {
         impl_error_chain_kind!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]
         );
     };
@@ -128,7 +116,7 @@ macro_rules! impl_error_chain_kind {
     ) => {
         impl_error_chain_kind!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]);
     };
     // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
@@ -141,7 +129,7 @@ macro_rules! impl_error_chain_kind {
     ) => {
         impl_error_chain_kind!(SORT [$( $def )*]
             items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
-            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
+            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
             queue [$( $tail )*]);
     };
     // Add braces and flush always on braces
@@ -199,27 +187,13 @@ macro_rules! impl_error_chain_kind {
         pub enum $name {
             $(
                 $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
+                $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*,
             )*
 
             #[doc(hidden)]
             __Nonexhaustive {}
         }
     };
-    // Private enum (Queue Empty)
-    (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*]
-        body [$($( #[$imeta:meta] )*
-            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
-        queue [ ]
-    ) => {
-        $(#[$meta])*
-        enum $name {
-            $(
-                $(#[$imeta])*
-                $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
-            )*
-        }
-    };
     // Unit variant
     (ENUM_DEFINITION [$( $def:tt )*]
         body [$($( #[$imeta:meta] )*
@@ -242,7 +216,7 @@ macro_rules! impl_error_chain_kind {
     ) => {
         impl_error_chain_kind!(ENUM_DEFINITION [ $($def)* ]
             body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
-                    $( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
+                    $( #[$qmeta] )* => $qitem (($( $qtyp ),+)) {} ]
             queue [ $($queue)* ]
         );
     };
@@ -264,7 +238,8 @@ macro_rules! impl_error_chain_kind {
             $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
         )*}
     ) => {
-        #[allow(unknown_lints, unused, unused_doc_comment)]
+        #[allow(unknown_lints, unused, renamed_and_removed_lints)]
+        #[allow(unused_doc_comment, unused_doc_comments)]
         impl ::std::fmt::Display for $name {
             fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                 -> ::std::fmt::Result
@@ -287,36 +262,8 @@ macro_rules! impl_error_chain_kind {
                 }
             }
         }
-        /*#[allow(unused)]
-        impl ::std::error::Error for $name {
-            fn description(&self) -> &str {
-                match *self {
-                    $(
-                        impl_error_chain_kind!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            impl_error_chain_kind!(FIND_DESCRIPTION_IMPL
-                                $item: $imode self fmt [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-            fn cause(&self) -> Option<&::std::error::Error> {
-                match *self {
-                    $(
-                        impl_error_chain_kind!(ITEM_PATTERN
-                            $name $item: $imode [$( ref $var ),*]
-                        ) => {
-                            impl_error_chain_kind!(FIND_CAUSE_IMPL
-                                $item: $imode [$( $var ),*]
-                                {$( $funcs )*})
-                        }
-                    )*
-                }
-            }
-        }*/
-        #[allow(unknown_lints, unused, unused_doc_comment)]
+        #[allow(unknown_lints, unused, renamed_and_removed_lints)]
+        #[allow(unused_doc_comment, unused_doc_comments)]
         impl $name {
             /// A string describing the error kind.
             pub fn description(&self) -> &str {
@@ -336,28 +283,23 @@ macro_rules! impl_error_chain_kind {
                 }
             }
         }
-        $(
-            impl_error_chain_kind!(FIND_FROM_IMPL
-                $name $item: $imode [$( $var:$typ ),*]
-                {$( $funcs )*});
-        )*
     };
     (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
         { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
     ) => {
         |impl_error_chain_kind!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| {
-            write!(f, $( $exprs )*)
+            write_internal!(f, $( $exprs )*)
         }
     };
     (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
         { display($pattern:expr) $( $tail:tt )*}
     ) => {
-        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) }
+        |_, f: &mut ::std::fmt::Formatter| { write_internal!(f, $pattern) }
     };
     (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
         { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
     ) => {
-        |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) }
+        |_, f: &mut ::std::fmt::Formatter| { write_internal!(f, $pattern, $( $exprs )*) }
     };
     (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
         { $t:tt $( $tail:tt )*}
@@ -370,7 +312,7 @@ macro_rules! impl_error_chain_kind {
         { }
     ) => {
         |self_: &$name, f: &mut ::std::fmt::Formatter| {
-            write!(f, "{}", self_.description())
+            write_internal!(f, "{}", self_.description())
         }
     };
     (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
@@ -391,97 +333,7 @@ macro_rules! impl_error_chain_kind {
         [$( $var:ident ),*]
         { }
     ) => {
-        stringify!($item)
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { cause($expr:expr) $( $tail:tt )*}
-    ) => {
-        Some($expr)
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        impl_error_chain_kind!(FIND_CAUSE_IMPL
-            $item: $imode [$( $var ),*]
-            { $($tail)* })
-    };
-    (FIND_CAUSE_IMPL $item:ident: $imode:tt
-        [$( $var:ident ),*]
-        { }
-    ) => {
-        None
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { from() $( $tail:tt )*}
-    ) => {
-        $(
-            impl From<$typ> for $name {
-                fn from($var: $typ) -> $name {
-                    $name::$item($var)
-                }
-            }
-        )*
-        impl_error_chain_kind!(FIND_FROM_IMPL
-            $name $item: $imode [$( $var:$typ ),*]
-            {$( $tail )*});
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: UNIT
-        [ ]
-        { from($ftyp:ty) $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from(_discarded_error: $ftyp) -> $name {
-                $name::$item
-            }
-        }
-        impl_error_chain_kind!(FIND_FROM_IMPL
-            $name $item: UNIT [  ]
-            {$( $tail )*});
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: TUPLE
-        [$( $var:ident: $typ:ty ),*]
-        { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from($fvar: $ftyp) -> $name {
-                $name::$item($( $texpr ),*)
-            }
-        }
-        impl_error_chain_kind!(FIND_FROM_IMPL
-            $name $item: TUPLE [$( $var:$typ ),*]
-            { $($tail)* });
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: STRUCT
-        [$( $var:ident: $typ:ty ),*]
-        { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
-    ) => {
-        impl From<$ftyp> for $name {
-            fn from($fvar: $ftyp) -> $name {
-                $name::$item {
-                    $( $tvar: $texpr ),*
-                }
-            }
-        }
-        impl_error_chain_kind!(FIND_FROM_IMPL
-            $name $item: STRUCT [$( $var:$typ ),*]
-            { $($tail)* });
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { $t:tt $( $tail:tt )*}
-    ) => {
-        impl_error_chain_kind!(FIND_FROM_IMPL
-            $name $item: $imode [$( $var:$typ ),*]
-            {$( $tail )*}
-        );
-    };
-    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
-        [$( $var:ident: $typ:ty ),*]
-        { }
-    ) => {
+        stringify_internal!($item)
     };
     (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
     ) => { };
@@ -521,16 +373,6 @@ macro_rules! impl_error_chain_kind {
     => { impl_error_chain_kind!(ERROR_CHECK_COMMA $imode $($tail)*); };
     (ERROR_CHECK $imode:tt description($expr:expr) $( $tail:tt )*)
     => { impl_error_chain_kind!(ERROR_CHECK_COMMA $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt cause($expr:expr) $($tail:tt)*)
-    => { impl_error_chain_kind!(ERROR_CHECK_COMMA $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt from() $($tail:tt)*)
-    => { impl_error_chain_kind!(ERROR_CHECK_COMMA $imode $($tail)*); };
-    (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*)
-    => { impl_error_chain_kind!(ERROR_CHECK_COMMA $imode $($tail)*); };
-    (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*)
-    => { impl_error_chain_kind!(ERROR_CHECK_COMMA TUPLE $($tail)*); };
-    (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
-        => { impl_error_chain_kind!(ERROR_CHECK_COMMA STRUCT $($tail)*); };
     (ERROR_CHECK $imode:tt ) => {};
     (ERROR_CHECK_COMMA $imode:tt , $( $tail:tt )*)
     => { impl_error_chain_kind!(ERROR_CHECK $imode $($tail)*); };
diff --git a/third_party/rust/error-chain/src/lib.rs b/third_party/rust/error-chain/src/lib.rs
index d0881fcef1c1b9639c4132a9391a57f809b058ef..43d2d5f479b034ffe779e126464564f15dccc1c8 100644
--- a/third_party/rust/error-chain/src/lib.rs
+++ b/third_party/rust/error-chain/src/lib.rs
@@ -1,6 +1,5 @@
 #![deny(missing_docs)]
-#![allow(unknown_lints)] // to be removed when unused_doc_comments lints is merged
-#![doc(html_root_url = "https://docs.rs/error-chain/0.11.0")]
+#![doc(html_root_url = "https://docs.rs/error-chain/0.12.4")]
 
 //! A library for consistent and reliable error handling
 //!
@@ -164,6 +163,10 @@
 //!             display("unknown toolchain version: '{}'", v), // trailing comma is allowed
 //!         }
 //!     }
+//!
+//!     // If this annotation is left off, a variant `Msg(s: String)` will be added, and `From`
+//!     // impls will be provided for `String` and `&str`
+//!     skip_msg_variant
 //! }
 //!
 //! # fn main() {}
@@ -536,21 +539,9 @@
 //! [`map_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err
 //! [`BacktraceFrame`]: https://docs.rs/backtrace/0.3.2/backtrace/struct.BacktraceFrame.html
 
-
-#[cfg(feature = "backtrace")]
-extern crate backtrace;
-
 use std::error;
-use std::iter::Iterator;
-#[cfg(feature = "backtrace")]
-use std::sync::Arc;
 use std::fmt;
-
-#[cfg(feature = "backtrace")]
-pub use backtrace::Backtrace;
-#[cfg(not(feature = "backtrace"))]
-/// Dummy type used when the `backtrace` feature is disabled.
-pub type Backtrace = ();
+use std::iter::Iterator;
 
 #[macro_use]
 mod impl_error_chain_kind;
@@ -559,27 +550,39 @@ mod error_chain;
 #[macro_use]
 mod quick_main;
 pub use quick_main::ExitCode;
+mod backtrace;
 #[cfg(feature = "example_generated")]
 pub mod example_generated;
+pub use backtrace::Backtrace;
+#[doc(hidden)]
+pub use backtrace::InternalBacktrace;
 
 #[derive(Debug)]
+#[allow(unknown_lints, bare_trait_objects)]
 /// Iterator over the error chain using the `Error::cause()` method.
 pub struct Iter<'a>(Option<&'a error::Error>);
 
 impl<'a> Iter<'a> {
     /// Returns a new iterator over the error chain using `Error::cause()`.
+    #[allow(unknown_lints, bare_trait_objects)]
     pub fn new(err: Option<&'a error::Error>) -> Iter<'a> {
         Iter(err)
     }
 }
 
+#[allow(unknown_lints, bare_trait_objects)]
 impl<'a> Iterator for Iter<'a> {
     type Item = &'a error::Error;
 
     fn next<'b>(&'b mut self) -> Option<&'a error::Error> {
         match self.0.take() {
             Some(e) => {
-                self.0 = e.cause();
+                self.0 = match () {
+                    #[cfg(not(has_error_source))]
+                    () => e.cause(),
+                    #[cfg(has_error_source)]
+                    () => e.source(),
+                };
                 Some(e)
             }
             None => None,
@@ -587,38 +590,6 @@ impl<'a> Iterator for Iter<'a> {
     }
 }
 
-/// Returns a backtrace of the current call stack if `RUST_BACKTRACE`
-/// is set to anything but ``0``, and `None` otherwise.  This is used
-/// in the generated error implementations.
-#[cfg(feature = "backtrace")]
-#[doc(hidden)]
-pub fn make_backtrace() -> Option<Arc<Backtrace>> {
-    use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
-
-    // The lowest bit indicates whether the value was computed,
-    // while the second lowest bit is the actual "enabled" bit.
-    static BACKTRACE_ENABLED_CACHE: AtomicUsize = ATOMIC_USIZE_INIT;
-
-    let enabled = match BACKTRACE_ENABLED_CACHE.load(Ordering::Relaxed) {
-        0 => {
-            let enabled = match std::env::var_os("RUST_BACKTRACE") {
-                Some(ref val) if val != "0" => true,
-                _ => false
-            };
-            let encoded = ((enabled as usize) << 1) | 1;
-            BACKTRACE_ENABLED_CACHE.store(encoded, Ordering::Relaxed);
-            enabled
-        }
-        encoded => (encoded >> 1) != 0
-    };
-
-    if enabled {
-        Some(Arc::new(Backtrace::new()))
-    } else {
-        None
-    }
-}
-
 /// This trait is implemented on all the errors generated by the `error_chain`
 /// macro.
 pub trait ChainedError: error::Error + Send + 'static {
@@ -626,13 +597,16 @@ pub trait ChainedError: error::Error + Send + 'static {
     type ErrorKind;
 
     /// Constructs an error from a kind, and generates a backtrace.
-    fn from_kind(kind: Self::ErrorKind) -> Self where Self: Sized;
+    fn from_kind(kind: Self::ErrorKind) -> Self
+    where
+        Self: Sized;
 
     /// Constructs a chained error from another error and a kind, and generates a backtrace.
     fn with_chain<E, K>(error: E, kind: K) -> Self
-        where Self: Sized,
-              E: ::std::error::Error + Send + 'static,
-              K: Into<Self::ErrorKind>;
+    where
+        Self: Sized,
+        E: ::std::error::Error + Send + 'static,
+        K: Into<Self::ErrorKind>;
 
     /// Returns the kind of the error.
     fn kind(&self) -> &Self::ErrorKind;
@@ -653,19 +627,23 @@ pub trait ChainedError: error::Error + Send + 'static {
 
     /// Extends the error chain with a new entry.
     fn chain_err<F, EK>(self, error: F) -> Self
-        where F: FnOnce() -> EK,
-              EK: Into<Self::ErrorKind>;
+    where
+        F: FnOnce() -> EK,
+        EK: Into<Self::ErrorKind>;
 
     /// Creates an error from its parts.
     #[doc(hidden)]
-    fn new(kind: Self::ErrorKind, state: State) -> Self where Self: Sized;
+    fn new(kind: Self::ErrorKind, state: State) -> Self
+    where
+        Self: Sized;
 
     /// Returns the first known backtrace, either from its State or from one
     /// of the errors from `foreign_links`.
-    #[cfg(feature = "backtrace")]
     #[doc(hidden)]
-    fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<Arc<Backtrace>>
-        where Self: Sized;
+    #[allow(unknown_lints, bare_trait_objects)]
+    fn extract_backtrace(e: &(error::Error + Send + 'static)) -> Option<InternalBacktrace>
+    where
+        Self: Sized;
 }
 
 /// A struct which formats an error for output.
@@ -673,18 +651,18 @@ pub trait ChainedError: error::Error + Send + 'static {
 pub struct DisplayChain<'a, T: 'a + ?Sized>(&'a T);
 
 impl<'a, T> fmt::Display for DisplayChain<'a, T>
-    where T: ChainedError
+where
+    T: ChainedError,
 {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        // Keep `try!` for 1.10 support
-        try!(writeln!(fmt, "Error: {}", self.0));
+        writeln!(fmt, "Error: {}", self.0)?;
 
         for e in self.0.iter().skip(1) {
-            try!(writeln!(fmt, "Caused by: {}", e));
+            writeln!(fmt, "Caused by: {}", e)?;
         }
 
-        if let Some(backtrace) = self.0.backtrace() {
-            try!(writeln!(fmt, "{:?}", backtrace));
+        if let Some(backtrace) = ChainedError::backtrace(self.0) {
+            writeln!(fmt, "{:?}", backtrace)?;
         }
 
         Ok(())
@@ -694,56 +672,37 @@ impl<'a, T> fmt::Display for DisplayChain<'a, T>
 /// Common state between errors.
 #[derive(Debug)]
 #[doc(hidden)]
+#[allow(unknown_lints, bare_trait_objects)]
 pub struct State {
     /// Next error in the error chain.
     pub next_error: Option<Box<error::Error + Send>>,
     /// Backtrace for the current error.
-    #[cfg(feature = "backtrace")]
-    pub backtrace: Option<Arc<Backtrace>>,
+    pub backtrace: InternalBacktrace,
 }
 
 impl Default for State {
-    #[cfg(feature = "backtrace")]
     fn default() -> State {
         State {
             next_error: None,
-            backtrace: make_backtrace(),
+            backtrace: InternalBacktrace::new(),
         }
     }
-
-    #[cfg(not(feature = "backtrace"))]
-    fn default() -> State {
-        State { next_error: None }
-    }
 }
 
 impl State {
     /// Creates a new State type
-    #[cfg(feature = "backtrace")]
+    #[allow(unknown_lints, bare_trait_objects)]
     pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State {
-        let backtrace = CE::extract_backtrace(&*e).or_else(make_backtrace);
+        let backtrace = CE::extract_backtrace(&*e).unwrap_or_else(InternalBacktrace::new);
         State {
             next_error: Some(e),
             backtrace: backtrace,
         }
     }
 
-    /// Creates a new State type
-    #[cfg(not(feature = "backtrace"))]
-    pub fn new<CE: ChainedError>(e: Box<error::Error + Send>) -> State {
-        State { next_error: Some(e) }
-    }
-
     /// Returns the inner backtrace if present.
-    #[cfg(feature = "backtrace")]
     pub fn backtrace(&self) -> Option<&Backtrace> {
-        self.backtrace.as_ref().map(|v| &**v)
-    }
-
-    /// Returns the inner backtrace if present.
-    #[cfg(not(feature = "backtrace"))]
-    pub fn backtrace(&self) -> Option<&Backtrace> {
-        None
+        self.backtrace.as_backtrace()
     }
 }
 
@@ -845,7 +804,7 @@ macro_rules! bail {
 /// ```
 ///
 /// See documentation for `bail!` macro for further details.
-#[macro_export]
+#[macro_export(local_inner_macros)]
 macro_rules! ensure {
     ($cond:expr, $e:expr) => {
         if !($cond) {
@@ -861,5 +820,5 @@ macro_rules! ensure {
 
 #[doc(hidden)]
 pub mod mock {
-    error_chain!{}
+    error_chain! {}
 }
diff --git a/third_party/rust/error-chain/src/quick_main.rs b/third_party/rust/error-chain/src/quick_main.rs
index f81e7d704aa313631f98fb0a215d83afe9f085fa..a6f093d2b3dac1246d9cc70ff469478c7bfda1be 100644
--- a/third_party/rust/error-chain/src/quick_main.rs
+++ b/third_party/rust/error-chain/src/quick_main.rs
@@ -42,13 +42,17 @@
 macro_rules! quick_main {
     ($main:expr) => {
         fn main() {
-            use ::std::io::Write;
+            use std::io::Write;
 
             ::std::process::exit(match $main() {
                 Ok(ret) => $crate::ExitCode::code(ret),
                 Err(ref e) => {
-                    write!(&mut ::std::io::stderr(), "{}", $crate::ChainedError::display_chain(e))
-                        .expect("Error writing to stderr");
+                    write!(
+                        &mut ::std::io::stderr(),
+                        "{}",
+                        $crate::ChainedError::display_chain(e)
+                    )
+                    .expect("Error writing to stderr");
 
                     1
                 }
diff --git a/third_party/rust/error-chain/tests/tests.rs b/third_party/rust/error-chain/tests/tests.rs
index e603e02af88a724beba44871319c05697aa77263..e9d183c5776478dc709b1746acdff537942beeca 100644
--- a/third_party/rust/error-chain/tests/tests.rs
+++ b/third_party/rust/error-chain/tests/tests.rs
@@ -177,7 +177,6 @@ fn order_test_7() {
     };
 }
 
-
 #[test]
 fn order_test_8() {
     error_chain! {
@@ -194,19 +193,30 @@ fn order_test_8() {
 
 #[test]
 fn empty() {
-    error_chain!{};
+    error_chain! {};
 }
 
 #[test]
 #[cfg(feature = "backtrace")]
 fn has_backtrace_depending_on_env() {
+    use std::path::PathBuf;
     use std::process::Command;
-    use std::path::Path;
+
+    let cmd_folder = if cfg!(build = "debug") {
+        "debug"
+    } else if cfg!(build = "release") {
+        "release"
+    } else {
+        panic!("Unknown build config");
+    };
 
     let cmd_path = if cfg!(windows) {
-        Path::new("./target/debug/has_backtrace.exe")
+        PathBuf::from(format!(
+            "./target/{}/examples/has_backtrace.exe",
+            cmd_folder
+        ))
     } else {
-        Path::new("./target/debug/has_backtrace")
+        PathBuf::from(format!("./target/{}/examples/has_backtrace", cmd_folder))
     };
     let mut cmd = Command::new(cmd_path);
 
@@ -265,7 +275,7 @@ fn error_chain_err() {
 #[test]
 fn links() {
     mod test {
-        error_chain!{}
+        error_chain! {}
     }
 
     error_chain! {
@@ -292,9 +302,15 @@ mod foreign_link_test {
             "Foreign error description"
         }
 
+        #[cfg(not(has_error_source))]
         fn cause(&self) -> Option<&::std::error::Error> {
             Some(&self.cause)
         }
+
+        #[cfg(has_error_source)]
+        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+            Some(&self.cause)
+        }
     }
 
     impl fmt::Display for ForeignError {
@@ -311,9 +327,15 @@ mod foreign_link_test {
             "Foreign error cause description"
         }
 
+        #[cfg(not(has_error_source))]
         fn cause(&self) -> Option<&::std::error::Error> {
             None
         }
+
+        #[cfg(has_error_source)]
+        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+            None
+        }
     }
 
     impl fmt::Display for ForeignErrorCause {
@@ -337,32 +359,66 @@ mod foreign_link_test {
     #[test]
     fn display_underlying_error() {
         let chained_error = try_foreign_error().err().unwrap();
-        assert_eq!(format!("{}", ForeignError { cause: ForeignErrorCause {} }),
-                   format!("{}", chained_error));
+        assert_eq!(
+            format!(
+                "{}",
+                ForeignError {
+                    cause: ForeignErrorCause {}
+                }
+            ),
+            format!("{}", chained_error)
+        );
     }
 
     #[test]
+    #[cfg(not(has_error_source))]
     fn finds_cause() {
         let chained_error = try_foreign_error().err().unwrap();
-        assert_eq!(format!("{}", ForeignErrorCause {}),
-                   format!("{}", ::std::error::Error::cause(&chained_error).unwrap()));
+        assert_eq!(
+            format!("{}", ForeignErrorCause {}),
+            format!("{}", ::std::error::Error::cause(&chained_error).unwrap())
+        );
+    }
+
+    #[test]
+    #[cfg(has_error_source)]
+    fn finds_source() {
+        let chained_error = try_foreign_error().err().unwrap();
+        assert_eq!(
+            format!("{}", ForeignErrorCause {}),
+            format!("{}", ::std::error::Error::source(&chained_error).unwrap())
+        );
     }
 
     #[test]
+    #[allow(unknown_lints, bare_trait_objects)]
     fn iterates() {
         let chained_error = try_foreign_error().err().unwrap();
         let mut error_iter = chained_error.iter();
         assert!(!format!("{:?}", error_iter).is_empty());
-        assert_eq!(format!("{}", ForeignError { cause: ForeignErrorCause {} }),
-                   format!("{}", error_iter.next().unwrap()));
-        assert_eq!(format!("{}", ForeignErrorCause {}),
-                   format!("{}", error_iter.next().unwrap()));
-        assert_eq!(format!("{:?}", None as Option<&::std::error::Error>),
-                   format!("{:?}", error_iter.next()));
+        assert_eq!(
+            format!(
+                "{}",
+                ForeignError {
+                    cause: ForeignErrorCause {}
+                }
+            ),
+            format!("{}", error_iter.next().unwrap())
+        );
+        assert_eq!(
+            format!("{}", ForeignErrorCause {}),
+            format!("{}", error_iter.next().unwrap())
+        );
+        assert_eq!(
+            format!("{:?}", None as Option<&::std::error::Error>),
+            format!("{:?}", error_iter.next())
+        );
     }
 
     fn try_foreign_error() -> Result<()> {
-        Err(ForeignError { cause: ForeignErrorCause {} })?;
+        Err(ForeignError {
+            cause: ForeignErrorCause {},
+        })?;
         Ok(())
     }
 }
@@ -374,7 +430,7 @@ mod attributes_test {
 
     #[cfg(not(test))]
     mod inner {
-        error_chain!{}
+        error_chain! {}
     }
 
     error_chain! {
@@ -422,7 +478,7 @@ fn without_result() {
 #[test]
 fn documentation() {
     mod inner {
-        error_chain!{}
+        error_chain! {}
     }
 
     error_chain! {
@@ -446,13 +502,13 @@ mod multiple_error_same_mod {
             MyError, MyErrorKind, MyResultExt, MyResult;
         }
     }
-    error_chain!{}
+    error_chain! {}
 }
 
 #[doc(test)]
 #[deny(dead_code)]
 mod allow_dead_code {
-    error_chain!{}
+    error_chain! {}
 }
 
 // Make sure links actually work!
@@ -485,8 +541,23 @@ fn error_patterns() {
 
     // Tuples look nice when matching errors
     match Error::from("Test") {
-        Error(ErrorKind::Msg(_), _) => {},
-        _ => {},
+        Error(ErrorKind::Msg(_), _) => {}
+        _ => {}
+    }
+}
+
+#[test]
+fn result_match() {
+    error_chain! {}
+
+    fn ok() -> Result<()> {
+        Ok(())
+    }
+
+    match ok() {
+        Ok(()) => {}
+        Err(Error(ErrorKind::Msg(_), _)) => {}
+        Err(..) => {}
     }
 }
 
@@ -563,7 +634,6 @@ fn types_declarations() {
 /// Calling chain_err over a `Result` containing an error to get a chained error
 /// and constructing a MyError directly, passing it an error should be equivalent.
 fn rewrapping() {
-
     use std::env::VarError::{self, NotPresent, NotUnicode};
 
     error_chain! {
@@ -589,9 +659,10 @@ fn rewrapping() {
         NotUnicode(_) => Err(e).chain_err(|| "env var was bork文字化ã"),
     });
 
-    assert_eq!(format!("{}", our_error_a.unwrap_err()),
-               format!("{}", our_error_b.unwrap_err()));
-
+    assert_eq!(
+        format!("{}", our_error_a.unwrap_err()),
+        format!("{}", our_error_b.unwrap_err())
+    );
 }
 
 #[test]
@@ -610,7 +681,6 @@ fn comma_in_errors_impl() {
     };
 }
 
-
 #[test]
 fn trailing_comma_in_errors_impl() {
     error_chain! {
@@ -626,3 +696,24 @@ fn trailing_comma_in_errors_impl() {
         }
     };
 }
+
+#[test]
+fn skipping_msg_variant() {
+    error_chain! {
+        skip_msg_variant
+
+        errors {
+            MyMsg(s: String) {
+                description(&s)
+                display("{}", s)
+            }
+        }
+    }
+
+    let x = Error::from_kind(ErrorKind::MyMsg("some string".into()));
+    // This would fail to compile if we generate a `Msg` variant
+    match *x.kind() {
+        ErrorKind::MyMsg(_) => {}
+        ErrorKind::__Nonexhaustive {} => {}
+    }
+}
diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml
index f6d4c34a5be22b8b31e50b3a2d9937e8860b2887..4f12880b95543434f3e75af34565522c1b1cab92 100644
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -23,10 +23,10 @@ webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
 cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "e012b2151fb6f0ffd50e91baa7756e77a3c416d9", optional = true }
 cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="df4dc0288b07b865440f4c7e41ca49ca9ccffc63", optional = true, features=["pulse-dlopen"] }
 cubeb-sys = { version = "0.10", optional = true, features=["gecko-in-tree"] }
-audioipc2-client = { git = "https://github.com/kinetiknz/audioipc-2", rev = "f8f611808168b7b1395b2e5dc17e5e6e2b975c6d", optional = true } # macos (v2) branch
-audioipc2-server = { git = "https://github.com/kinetiknz/audioipc-2", rev = "f8f611808168b7b1395b2e5dc17e5e6e2b975c6d", optional = true } # macos (v2) branch
-audioipc-client = { git = "https://github.com/mozilla/audioipc-2", rev = "405b8208a8fb32e13db87c252aba9b371ae47859", optional = true }
-audioipc-server = { git = "https://github.com/mozilla/audioipc-2", rev = "405b8208a8fb32e13db87c252aba9b371ae47859", optional = true }
+audioipc2-client = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
+audioipc2-server = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
+audioipc-client = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
+audioipc-server = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
 encoding_glue = { path = "../../../../intl/encoding_glue" }
 authenticator = "0.3.1"
 gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }