summaryrefslogtreecommitdiffstats
path: root/third_party/rust/anyhow
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/anyhow
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/anyhow')
-rw-r--r--third_party/rust/anyhow/.cargo-checksum.json1
-rw-r--r--third_party/rust/anyhow/Cargo.toml43
-rw-r--r--third_party/rust/anyhow/LICENSE-APACHE201
-rw-r--r--third_party/rust/anyhow/LICENSE-MIT23
-rw-r--r--third_party/rust/anyhow/README.md176
-rw-r--r--third_party/rust/anyhow/build.rs63
-rw-r--r--third_party/rust/anyhow/src/backtrace.rs36
-rw-r--r--third_party/rust/anyhow/src/chain.rs101
-rw-r--r--third_party/rust/anyhow/src/context.rs177
-rw-r--r--third_party/rust/anyhow/src/error.rs802
-rw-r--r--third_party/rust/anyhow/src/fmt.rs149
-rw-r--r--third_party/rust/anyhow/src/kind.rs116
-rw-r--r--third_party/rust/anyhow/src/lib.rs603
-rw-r--r--third_party/rust/anyhow/src/macros.rs163
-rw-r--r--third_party/rust/anyhow/src/wrapper.rs78
-rw-r--r--third_party/rust/anyhow/tests/common/mod.rs14
-rw-r--r--third_party/rust/anyhow/tests/compiletest.rs6
-rw-r--r--third_party/rust/anyhow/tests/drop/mod.rs52
-rw-r--r--third_party/rust/anyhow/tests/test_autotrait.rs13
-rw-r--r--third_party/rust/anyhow/tests/test_backtrace.rs13
-rw-r--r--third_party/rust/anyhow/tests/test_boxed.rs40
-rw-r--r--third_party/rust/anyhow/tests/test_chain.rs45
-rw-r--r--third_party/rust/anyhow/tests/test_context.rs159
-rw-r--r--third_party/rust/anyhow/tests/test_convert.rs24
-rw-r--r--third_party/rust/anyhow/tests/test_downcast.rs106
-rw-r--r--third_party/rust/anyhow/tests/test_fmt.rs94
-rw-r--r--third_party/rust/anyhow/tests/test_macros.rs33
-rw-r--r--third_party/rust/anyhow/tests/test_repr.rs29
-rw-r--r--third_party/rust/anyhow/tests/test_source.rs62
-rw-r--r--third_party/rust/anyhow/tests/ui/no-impl.rs8
-rw-r--r--third_party/rust/anyhow/tests/ui/no-impl.stderr21
31 files changed, 3451 insertions, 0 deletions
diff --git a/third_party/rust/anyhow/.cargo-checksum.json b/third_party/rust/anyhow/.cargo-checksum.json
new file mode 100644
index 0000000000..015dd54c4a
--- /dev/null
+++ b/third_party/rust/anyhow/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"76e6e0a729a4038b0d8bcdd36a054e96f3e93dc1922813f512d28cdf8d21e516","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0d9c5facc3db17123752af8c3dbcdb9bb3785c8ed046b27de26669e4e87f131c","build.rs":"d8b58acc2cd88d627763135b3b25b46f276e2672ef740efb7fb5b1404fb230d8","src/backtrace.rs":"a82a8ffae2c68ee385dc78d8ec8cb6f3351234f0ad6af7e87df2371593e0f6aa","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"f2be36af9588c924ed087bcb7bd681d330889e54b8f98cdc2aba93512a28762e","src/error.rs":"2c6a51880c7379265f7f7b6557e7bed808ff0f3267337a0c77dbbc1d2c4662e7","src/fmt.rs":"079d7b4faaa23f42423e0bb6b4e8a80d7d6d45c38c0d46bebd7d647c8679469f","src/kind.rs":"8481a8b7835eebb3859a8c32c217bf9c73543cfc62e3916b98d39af8b063125c","src/lib.rs":"119a39d1062a4b99a9f888a9f595a48fabacba6c8f2c3c59361ce2065d938ef6","src/macros.rs":"77722190b58a6106b21aefd3b5d4f136a076afcdbc0fae21562d99e2c22912e1","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/drop/mod.rs":"464bc1ddeae307eac906928286ec3edb77057c5c1302e02150d3649e2b861f1a","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"98a45325b1e86d4c5d3094ab99cd1ada1f771c505d2d7322f0afcbe7bdb71cfa","tests/test_chain.rs":"f28efeae7395d1c395e6f1a647b4199c25a00410ade45248c145c6fcf2fb448a","tests/test_context.rs":"f82c915b182df1a604a4cd558a03b1a821414983d6f6af6822398104cea70676","tests/test_convert.rs":"62840be1ee8022ba5e8c0d3fc1752a1526b2c47d4cceecff2b86790524c3b3ea","tests/test_downcast.rs":"253d6f54e554965023b378b037827ec6289c4779a7a7c12706e19c2731d219fe","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"c7d3d5e0b756f59d4858035025fb341d031369c88486fd9f961ee16bae6c78bf","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"7c2c3f46c266a437300591f10be330f937ac6a0a2213ed5030a9fbc895e2d100"},"package":"2494382e9ba43995f3c56359e518641f450f5c36feeb4632a75cde2ec297c867"} \ No newline at end of file
diff --git a/third_party/rust/anyhow/Cargo.toml b/third_party/rust/anyhow/Cargo.toml
new file mode 100644
index 0000000000..5ae385777f
--- /dev/null
+++ b/third_party/rust/anyhow/Cargo.toml
@@ -0,0 +1,43 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "anyhow"
+version = "1.0.30"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "Flexible concrete Error type built on std::error::Error"
+documentation = "https://docs.rs/anyhow"
+readme = "README.md"
+categories = ["rust-patterns"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/anyhow"
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "doc_cfg"]
+targets = ["x86_64-unknown-linux-gnu"]
+[dev-dependencies.futures]
+version = "0.3"
+default-features = false
+
+[dev-dependencies.rustversion]
+version = "1.0"
+
+[dev-dependencies.thiserror]
+version = "1.0"
+
+[dev-dependencies.trybuild]
+version = "1.0.19"
+features = ["diff"]
+
+[features]
+default = ["std"]
+std = []
diff --git a/third_party/rust/anyhow/LICENSE-APACHE b/third_party/rust/anyhow/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/anyhow/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/anyhow/LICENSE-MIT b/third_party/rust/anyhow/LICENSE-MIT
new file mode 100644
index 0000000000..31aa79387f
--- /dev/null
+++ b/third_party/rust/anyhow/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/anyhow/README.md b/third_party/rust/anyhow/README.md
new file mode 100644
index 0000000000..87b41d7958
--- /dev/null
+++ b/third_party/rust/anyhow/README.md
@@ -0,0 +1,176 @@
+Anyhow&ensp;¯\\\_(ツ)\_/¯
+=========================
+
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/anyhow-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/anyhow)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/anyhow.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/anyhow)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-anyhow-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/anyhow)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/anyhow/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster)
+
+This library provides [`anyhow::Error`][Error], a trait object based error type
+for easy idiomatic error handling in Rust applications.
+
+[Error]: https://docs.rs/anyhow/1.0/anyhow/struct.Error.html
+
+```toml
+[dependencies]
+anyhow = "1.0"
+```
+
+*Compiler support: requires rustc 1.34+*
+
+<br>
+
+## Details
+
+- Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as the
+ return type of any fallible function.
+
+ Within the function, use `?` to easily propagate any error that implements the
+ `std::error::Error` trait.
+
+ ```rust
+ use anyhow::Result;
+
+ fn get_cluster_info() -> Result<ClusterMap> {
+ let config = std::fs::read_to_string("cluster.json")?;
+ let map: ClusterMap = serde_json::from_str(&config)?;
+ Ok(map)
+ }
+ ```
+
+- Attach context to help the person troubleshooting the error understand where
+ things went wrong. A low-level error like "No such file or directory" can be
+ annoying to debug without more context about what higher level step the
+ application was in the middle of.
+
+ ```rust
+ use anyhow::{Context, Result};
+
+ fn main() -> Result<()> {
+ ...
+ it.detach().context("Failed to detach the important thing")?;
+
+ let content = std::fs::read(path)
+ .with_context(|| format!("Failed to read instrs from {}", path))?;
+ ...
+ }
+ ```
+
+ ```console
+ Error: Failed to read instrs from ./path/to/instrs.json
+
+ Caused by:
+ No such file or directory (os error 2)
+ ```
+
+- Downcasting is supported and can be by value, by shared reference, or by
+ mutable reference as needed.
+
+ ```rust
+ // If the error was caused by redaction, then return a
+ // tombstone instead of the content.
+ match root_cause.downcast_ref::<DataStoreError>() {
+ Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
+ None => Err(error),
+ }
+ ```
+
+- If using the nightly channel, a backtrace is captured and printed with the
+ error if the underlying error type does not already provide its own. In order
+ to see backtraces, they must be enabled through the environment variables
+ described in [`std::backtrace`]:
+
+ - If you want panics and errors to both have backtraces, set
+ `RUST_BACKTRACE=1`;
+ - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
+ - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
+ `RUST_LIB_BACKTRACE=0`.
+
+ The tracking issue for this feature is [rust-lang/rust#53487].
+
+ [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
+ [rust-lang/rust#53487]: https://github.com/rust-lang/rust/issues/53487
+
+- Anyhow works with any error type that has an impl of `std::error::Error`,
+ including ones defined in your crate. We do not bundle a `derive(Error)` macro
+ but you can write the impls yourself or use a standalone macro like
+ [thiserror].
+
+ ```rust
+ use thiserror::Error;
+
+ #[derive(Error, Debug)]
+ pub enum FormatError {
+ #[error("Invalid header (expected {expected:?}, got {found:?})")]
+ InvalidHeader {
+ expected: String,
+ found: String,
+ },
+ #[error("Missing attribute: {0}")]
+ MissingAttribute(String),
+ }
+ ```
+
+- One-off error messages can be constructed using the `anyhow!` macro, which
+ supports string interpolation and produces an `anyhow::Error`.
+
+ ```rust
+ return Err(anyhow!("Missing attribute: {}", missing));
+ ```
+
+<br>
+
+## No-std support
+
+In no_std mode, the same API is almost all available and works the same way. To
+depend on Anyhow in no_std mode, disable our default enabled "std" feature in
+Cargo.toml. A global allocator is required.
+
+```toml
+[dependencies]
+anyhow = { version = "1.0", default-features = false }
+```
+
+Since the `?`-based error conversions would normally rely on the
+`std::error::Error` trait which is only available through std, no_std mode will
+require an explicit `.map_err(Error::msg)` when working with a non-Anyhow error
+type inside a function that returns Anyhow's error type.
+
+<br>
+
+## Comparison to failure
+
+The `anyhow::Error` type works something like `failure::Error`, but unlike
+failure ours is built around the standard library's `std::error::Error` trait
+rather than a separate trait `failure::Fail`. The standard library has adopted
+the necessary improvements for this to be possible as part of [RFC 2504].
+
+[RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
+
+<br>
+
+## Comparison to thiserror
+
+Use Anyhow if you don't care what error type your functions return, you just
+want it to be easy. This is common in application code. Use [thiserror] if you
+are a library that wants to design your own dedicated error type(s) so that on
+failures the caller gets exactly the information that you choose.
+
+[thiserror]: https://github.com/dtolnay/thiserror
+
+<br>
+
+#### License
+
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/third_party/rust/anyhow/build.rs b/third_party/rust/anyhow/build.rs
new file mode 100644
index 0000000000..d20b0721db
--- /dev/null
+++ b/third_party/rust/anyhow/build.rs
@@ -0,0 +1,63 @@
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::{Command, ExitStatus, Stdio};
+
+// This code exercises the surface area that we expect of the std Backtrace
+// type. If the current toolchain is able to compile it, we go ahead and use
+// backtrace in anyhow.
+const PROBE: &str = r#"
+ #![feature(backtrace)]
+ #![allow(dead_code)]
+
+ use std::backtrace::{Backtrace, BacktraceStatus};
+ use std::error::Error;
+ use std::fmt::{self, Display};
+
+ #[derive(Debug)]
+ struct E;
+
+ impl Display for E {
+ fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
+ unimplemented!()
+ }
+ }
+
+ impl Error for E {
+ fn backtrace(&self) -> Option<&Backtrace> {
+ let backtrace = Backtrace::capture();
+ match backtrace.status() {
+ BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {}
+ }
+ unimplemented!()
+ }
+ }
+"#;
+
+fn main() {
+ if !cfg!(feature = "std") {
+ return;
+ }
+ match compile_probe() {
+ Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"),
+ _ => {}
+ }
+}
+
+fn compile_probe() -> Option<ExitStatus> {
+ let rustc = env::var_os("RUSTC")?;
+ let out_dir = env::var_os("OUT_DIR")?;
+ let probefile = Path::new(&out_dir).join("probe.rs");
+ fs::write(&probefile, PROBE).ok()?;
+ Command::new(rustc)
+ .stderr(Stdio::null())
+ .arg("--edition=2018")
+ .arg("--crate-name=anyhow_build")
+ .arg("--crate-type=lib")
+ .arg("--emit=metadata")
+ .arg("--out-dir")
+ .arg(out_dir)
+ .arg(probefile)
+ .status()
+ .ok()
+}
diff --git a/third_party/rust/anyhow/src/backtrace.rs b/third_party/rust/anyhow/src/backtrace.rs
new file mode 100644
index 0000000000..01e33cb237
--- /dev/null
+++ b/third_party/rust/anyhow/src/backtrace.rs
@@ -0,0 +1,36 @@
+#[cfg(backtrace)]
+pub(crate) use std::backtrace::Backtrace;
+
+#[cfg(not(backtrace))]
+pub(crate) enum Backtrace {}
+
+#[cfg(backtrace)]
+macro_rules! backtrace {
+ () => {
+ Some(Backtrace::capture())
+ };
+}
+
+#[cfg(not(backtrace))]
+macro_rules! backtrace {
+ () => {
+ None
+ };
+}
+
+#[cfg(backtrace)]
+macro_rules! backtrace_if_absent {
+ ($err:expr) => {
+ match $err.backtrace() {
+ Some(_) => None,
+ None => Some(Backtrace::capture()),
+ }
+ };
+}
+
+#[cfg(all(feature = "std", not(backtrace)))]
+macro_rules! backtrace_if_absent {
+ ($err:expr) => {
+ None
+ };
+}
diff --git a/third_party/rust/anyhow/src/chain.rs b/third_party/rust/anyhow/src/chain.rs
new file mode 100644
index 0000000000..207e4f0ca9
--- /dev/null
+++ b/third_party/rust/anyhow/src/chain.rs
@@ -0,0 +1,101 @@
+use self::ChainState::*;
+use crate::StdError;
+
+#[cfg(feature = "std")]
+use std::vec;
+
+#[cfg(feature = "std")]
+pub(crate) use crate::Chain;
+
+#[cfg(not(feature = "std"))]
+pub(crate) struct Chain<'a> {
+ state: ChainState<'a>,
+}
+
+#[derive(Clone)]
+pub(crate) enum ChainState<'a> {
+ Linked {
+ next: Option<&'a (dyn StdError + 'static)>,
+ },
+ #[cfg(feature = "std")]
+ Buffered {
+ rest: vec::IntoIter<&'a (dyn StdError + 'static)>,
+ },
+}
+
+impl<'a> Chain<'a> {
+ pub fn new(head: &'a (dyn StdError + 'static)) -> Self {
+ Chain {
+ state: ChainState::Linked { next: Some(head) },
+ }
+ }
+}
+
+impl<'a> Iterator for Chain<'a> {
+ type Item = &'a (dyn StdError + 'static);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match &mut self.state {
+ Linked { next } => {
+ let error = (*next)?;
+ *next = error.source();
+ Some(error)
+ }
+ #[cfg(feature = "std")]
+ Buffered { rest } => rest.next(),
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.len();
+ (len, Some(len))
+ }
+}
+
+#[cfg(feature = "std")]
+impl DoubleEndedIterator for Chain<'_> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ match &mut self.state {
+ Linked { mut next } => {
+ let mut rest = Vec::new();
+ while let Some(cause) = next {
+ next = cause.source();
+ rest.push(cause);
+ }
+ let mut rest = rest.into_iter();
+ let last = rest.next_back();
+ self.state = Buffered { rest };
+ last
+ }
+ Buffered { rest } => rest.next_back(),
+ }
+ }
+}
+
+impl ExactSizeIterator for Chain<'_> {
+ fn len(&self) -> usize {
+ match &self.state {
+ Linked { mut next } => {
+ let mut len = 0;
+ while let Some(cause) = next {
+ next = cause.source();
+ len += 1;
+ }
+ len
+ }
+ #[cfg(feature = "std")]
+ Buffered { rest } => rest.len(),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl Default for Chain<'_> {
+ fn default() -> Self {
+ Chain {
+ state: ChainState::Buffered {
+ rest: Vec::new().into_iter(),
+ },
+ }
+ }
+}
diff --git a/third_party/rust/anyhow/src/context.rs b/third_party/rust/anyhow/src/context.rs
new file mode 100644
index 0000000000..25d34114c1
--- /dev/null
+++ b/third_party/rust/anyhow/src/context.rs
@@ -0,0 +1,177 @@
+use crate::error::ContextError;
+use crate::{Context, Error, StdError};
+use core::convert::Infallible;
+use core::fmt::{self, Debug, Display, Write};
+
+#[cfg(backtrace)]
+use std::backtrace::Backtrace;
+
+mod ext {
+ use super::*;
+
+ pub trait StdError {
+ fn ext_context<C>(self, context: C) -> Error
+ where
+ C: Display + Send + Sync + 'static;
+ }
+
+ #[cfg(feature = "std")]
+ impl<E> StdError for E
+ where
+ E: std::error::Error + Send + Sync + 'static,
+ {
+ fn ext_context<C>(self, context: C) -> Error
+ where
+ C: Display + Send + Sync + 'static,
+ {
+ let backtrace = backtrace_if_absent!(self);
+ Error::from_context(context, self, backtrace)
+ }
+ }
+
+ impl StdError for Error {
+ fn ext_context<C>(self, context: C) -> Error
+ where
+ C: Display + Send + Sync + 'static,
+ {
+ self.context(context)
+ }
+ }
+}
+
+impl<T, E> Context<T, E> for Result<T, E>
+where
+ E: ext::StdError + Send + Sync + 'static,
+{
+ fn context<C>(self, context: C) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ {
+ self.map_err(|error| error.ext_context(context))
+ }
+
+ fn with_context<C, F>(self, context: F) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ F: FnOnce() -> C,
+ {
+ self.map_err(|error| error.ext_context(context()))
+ }
+}
+
+/// ```
+/// # type T = ();
+/// #
+/// use anyhow::{Context, Result};
+///
+/// fn maybe_get() -> Option<T> {
+/// # const IGNORE: &str = stringify! {
+/// ...
+/// # };
+/// # unimplemented!()
+/// }
+///
+/// fn demo() -> Result<()> {
+/// let t = maybe_get().context("there is no T")?;
+/// # const IGNORE: &str = stringify! {
+/// ...
+/// # };
+/// # unimplemented!()
+/// }
+/// ```
+impl<T> Context<T, Infallible> for Option<T> {
+ fn context<C>(self, context: C) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ {
+ self.ok_or_else(|| Error::from_display(context, backtrace!()))
+ }
+
+ fn with_context<C, F>(self, context: F) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ F: FnOnce() -> C,
+ {
+ self.ok_or_else(|| Error::from_display(context(), backtrace!()))
+ }
+}
+
+impl<C, E> Debug for ContextError<C, E>
+where
+ C: Display,
+ E: Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Error")
+ .field("context", &Quoted(&self.context))
+ .field("source", &self.error)
+ .finish()
+ }
+}
+
+impl<C, E> Display for ContextError<C, E>
+where
+ C: Display,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.context, f)
+ }
+}
+
+impl<C, E> StdError for ContextError<C, E>
+where
+ C: Display,
+ E: StdError + 'static,
+{
+ #[cfg(backtrace)]
+ fn backtrace(&self) -> Option<&Backtrace> {
+ self.error.backtrace()
+ }
+
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ Some(&self.error)
+ }
+}
+
+impl<C> StdError for ContextError<C, Error>
+where
+ C: Display,
+{
+ #[cfg(backtrace)]
+ fn backtrace(&self) -> Option<&Backtrace> {
+ Some(self.error.backtrace())
+ }
+
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ Some(self.error.inner.error())
+ }
+}
+
+struct Quoted<C>(C);
+
+impl<C> Debug for Quoted<C>
+where
+ C: Display,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_char('"')?;
+ Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
+ formatter.write_char('"')?;
+ Ok(())
+ }
+}
+
+impl Write for Quoted<&mut fmt::Formatter<'_>> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ Display::fmt(&s.escape_debug(), self.0)
+ }
+}
+
+pub(crate) mod private {
+ use super::*;
+
+ pub trait Sealed {}
+
+ impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
+ impl<T> Sealed for Option<T> {}
+}
diff --git a/third_party/rust/anyhow/src/error.rs b/third_party/rust/anyhow/src/error.rs
new file mode 100644
index 0000000000..80d879f84e
--- /dev/null
+++ b/third_party/rust/anyhow/src/error.rs
@@ -0,0 +1,802 @@
+use crate::alloc::Box;
+use crate::backtrace::Backtrace;
+use crate::chain::Chain;
+use crate::{Error, StdError};
+use core::any::TypeId;
+use core::fmt::{self, Debug, Display};
+use core::mem::{self, ManuallyDrop};
+use core::ptr::{self, NonNull};
+
+#[cfg(feature = "std")]
+use core::ops::{Deref, DerefMut};
+
+impl Error {
+ /// Create a new error object from any error type.
+ ///
+ /// The error type must be threadsafe and `'static`, so that the `Error`
+ /// will be as well.
+ ///
+ /// If the error type does not provide a backtrace, a backtrace will be
+ /// created here to ensure that a backtrace exists.
+ #[cfg(feature = "std")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+ pub fn new<E>(error: E) -> Self
+ where
+ E: StdError + Send + Sync + 'static,
+ {
+ let backtrace = backtrace_if_absent!(error);
+ Error::from_std(error, backtrace)
+ }
+
+ /// Create a new error object from a printable error message.
+ ///
+ /// If the argument implements std::error::Error, prefer `Error::new`
+ /// instead which preserves the underlying error's cause chain and
+ /// backtrace. If the argument may or may not implement std::error::Error
+ /// now or in the future, use `anyhow!(err)` which handles either way
+ /// correctly.
+ ///
+ /// `Error::msg("...")` is equivalent to `anyhow!("...")` but occasionally
+ /// convenient in places where a function is preferable over a macro, such
+ /// as iterator or stream combinators:
+ ///
+ /// ```
+ /// # mod ffi {
+ /// # pub struct Input;
+ /// # pub struct Output;
+ /// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> {
+ /// # unimplemented!()
+ /// # }
+ /// # }
+ /// #
+ /// # use ffi::{Input, Output};
+ /// #
+ /// use anyhow::{Error, Result};
+ /// use futures::stream::{Stream, StreamExt, TryStreamExt};
+ ///
+ /// async fn demo<S>(stream: S) -> Result<Vec<Output>>
+ /// where
+ /// S: Stream<Item = Input>,
+ /// {
+ /// stream
+ /// .then(ffi::do_some_work) // returns Result<Output, &str>
+ /// .map_err(Error::msg)
+ /// .try_collect()
+ /// .await
+ /// }
+ /// ```
+ pub fn msg<M>(message: M) -> Self
+ where
+ M: Display + Debug + Send + Sync + 'static,
+ {
+ Error::from_adhoc(message, backtrace!())
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) fn from_std<E>(error: E, backtrace: Option<Backtrace>) -> Self
+ where
+ E: StdError + Send + Sync + 'static,
+ {
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<E>,
+ object_ref: object_ref::<E>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<E>,
+ object_boxed: object_boxed::<E>,
+ object_downcast: object_downcast::<E>,
+ object_drop_rest: object_drop_front::<E>,
+ };
+
+ // Safety: passing vtable that operates on the right type E.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ pub(crate) fn from_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
+ where
+ M: Display + Debug + Send + Sync + 'static,
+ {
+ use crate::wrapper::MessageError;
+ let error: MessageError<M> = MessageError(message);
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<MessageError<M>>,
+ object_ref: object_ref::<MessageError<M>>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<MessageError<M>>,
+ object_boxed: object_boxed::<MessageError<M>>,
+ object_downcast: object_downcast::<M>,
+ object_drop_rest: object_drop_front::<M>,
+ };
+
+ // Safety: MessageError is repr(transparent) so it is okay for the
+ // vtable to allow casting the MessageError<M> to M.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ pub(crate) fn from_display<M>(message: M, backtrace: Option<Backtrace>) -> Self
+ where
+ M: Display + Send + Sync + 'static,
+ {
+ use crate::wrapper::DisplayError;
+ let error: DisplayError<M> = DisplayError(message);
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<DisplayError<M>>,
+ object_ref: object_ref::<DisplayError<M>>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<DisplayError<M>>,
+ object_boxed: object_boxed::<DisplayError<M>>,
+ object_downcast: object_downcast::<M>,
+ object_drop_rest: object_drop_front::<M>,
+ };
+
+ // Safety: DisplayError is repr(transparent) so it is okay for the
+ // vtable to allow casting the DisplayError<M> to M.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) fn from_context<C, E>(context: C, error: E, backtrace: Option<Backtrace>) -> Self
+ where
+ C: Display + Send + Sync + 'static,
+ E: StdError + Send + Sync + 'static,
+ {
+ let error: ContextError<C, E> = ContextError { context, error };
+
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<ContextError<C, E>>,
+ object_ref: object_ref::<ContextError<C, E>>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<ContextError<C, E>>,
+ object_boxed: object_boxed::<ContextError<C, E>>,
+ object_downcast: context_downcast::<C, E>,
+ object_drop_rest: context_drop_rest::<C, E>,
+ };
+
+ // Safety: passing vtable that operates on the right type.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) fn from_boxed(
+ error: Box<dyn StdError + Send + Sync>,
+ backtrace: Option<Backtrace>,
+ ) -> Self {
+ use crate::wrapper::BoxedError;
+ let error = BoxedError(error);
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<BoxedError>,
+ object_ref: object_ref::<BoxedError>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<BoxedError>,
+ object_boxed: object_boxed::<BoxedError>,
+ object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
+ object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
+ };
+
+ // Safety: BoxedError is repr(transparent) so it is okay for the vtable
+ // to allow casting to Box<dyn StdError + Send + Sync>.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ // Takes backtrace as argument rather than capturing it here so that the
+ // user sees one fewer layer of wrapping noise in the backtrace.
+ //
+ // Unsafe because the given vtable must have sensible behavior on the error
+ // value of type E.
+ unsafe fn construct<E>(
+ error: E,
+ vtable: &'static ErrorVTable,
+ backtrace: Option<Backtrace>,
+ ) -> Self
+ where
+ E: StdError + Send + Sync + 'static,
+ {
+ let inner = Box::new(ErrorImpl {
+ vtable,
+ backtrace,
+ _object: error,
+ });
+ // Erase the concrete type of E from the compile-time type system. This
+ // is equivalent to the safe unsize coersion from Box<ErrorImpl<E>> to
+ // Box<ErrorImpl<dyn StdError + Send + Sync + 'static>> except that the
+ // result is a thin pointer. The necessary behavior for manipulating the
+ // underlying ErrorImpl<E> is preserved in the vtable provided by the
+ // caller rather than a builtin fat pointer vtable.
+ let erased = mem::transmute::<Box<ErrorImpl<E>>, Box<ErrorImpl<()>>>(inner);
+ let inner = ManuallyDrop::new(erased);
+ Error { inner }
+ }
+
+ /// Wrap the error value with additional context.
+ ///
+ /// For attaching context to a `Result` as it is propagated, the
+ /// [`Context`][crate::Context] extension trait may be more convenient than
+ /// this function.
+ ///
+ /// The primary reason to use `error.context(...)` instead of
+ /// `result.context(...)` via the `Context` trait would be if the context
+ /// needs to depend on some data held by the underlying error:
+ ///
+ /// ```
+ /// # use std::fmt::{self, Debug, Display};
+ /// #
+ /// # type T = ();
+ /// #
+ /// # impl std::error::Error for ParseError {}
+ /// # impl Debug for ParseError {
+ /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ /// # unimplemented!()
+ /// # }
+ /// # }
+ /// # impl Display for ParseError {
+ /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ /// # unimplemented!()
+ /// # }
+ /// # }
+ /// #
+ /// use anyhow::Result;
+ /// use std::fs::File;
+ /// use std::path::Path;
+ ///
+ /// struct ParseError {
+ /// line: usize,
+ /// column: usize,
+ /// }
+ ///
+ /// fn parse_impl(file: File) -> Result<T, ParseError> {
+ /// # const IGNORE: &str = stringify! {
+ /// ...
+ /// # };
+ /// # unimplemented!()
+ /// }
+ ///
+ /// pub fn parse(path: impl AsRef<Path>) -> Result<T> {
+ /// let file = File::open(&path)?;
+ /// parse_impl(file).map_err(|error| {
+ /// let context = format!(
+ /// "only the first {} lines of {} are valid",
+ /// error.line, path.as_ref().display(),
+ /// );
+ /// anyhow::Error::new(error).context(context)
+ /// })
+ /// }
+ /// ```
+ pub fn context<C>(self, context: C) -> Self
+ where
+ C: Display + Send + Sync + 'static,
+ {
+ let error: ContextError<C, Error> = ContextError {
+ context,
+ error: self,
+ };
+
+ let vtable = &ErrorVTable {
+ object_drop: object_drop::<ContextError<C, Error>>,
+ object_ref: object_ref::<ContextError<C, Error>>,
+ #[cfg(feature = "std")]
+ object_mut: object_mut::<ContextError<C, Error>>,
+ object_boxed: object_boxed::<ContextError<C, Error>>,
+ object_downcast: context_chain_downcast::<C>,
+ object_drop_rest: context_chain_drop_rest::<C>,
+ };
+
+ // As the cause is anyhow::Error, we already have a backtrace for it.
+ let backtrace = None;
+
+ // Safety: passing vtable that operates on the right type.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ /// Get the backtrace for this Error.
+ ///
+ /// Backtraces are only available on the nightly channel. Tracking issue:
+ /// [rust-lang/rust#53487][tracking].
+ ///
+ /// In order for the backtrace to be meaningful, one of the two environment
+ /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined
+ /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat
+ /// expensive to capture in Rust, so we don't necessarily want to be
+ /// capturing them all over the place all the time.
+ ///
+ /// - If you want panics and errors to both have backtraces, set
+ /// `RUST_BACKTRACE=1`;
+ /// - If you want only errors to have backtraces, set
+ /// `RUST_LIB_BACKTRACE=1`;
+ /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
+ /// `RUST_LIB_BACKTRACE=0`.
+ ///
+ /// [tracking]: https://github.com/rust-lang/rust/issues/53487
+ #[cfg(backtrace)]
+ pub fn backtrace(&self) -> &Backtrace {
+ self.inner.backtrace()
+ }
+
+ /// An iterator of the chain of source errors contained by this Error.
+ ///
+ /// This iterator will visit every error in the cause chain of this error
+ /// object, beginning with the error that this error object was created
+ /// from.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use anyhow::Error;
+ /// use std::io;
+ ///
+ /// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
+ /// for cause in error.chain() {
+ /// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
+ /// return Some(io_error.kind());
+ /// }
+ /// }
+ /// None
+ /// }
+ /// ```
+ #[cfg(feature = "std")]
+ pub fn chain(&self) -> Chain {
+ self.inner.chain()
+ }
+
+ /// The lowest level cause of this error &mdash; this error's cause's
+ /// cause's cause etc.
+ ///
+ /// The root cause is the last error in the iterator produced by
+ /// [`chain()`][Error::chain].
+ #[cfg(feature = "std")]
+ pub fn root_cause(&self) -> &(dyn StdError + 'static) {
+ let mut chain = self.chain();
+ let mut root_cause = chain.next().unwrap();
+ for cause in chain {
+ root_cause = cause;
+ }
+ root_cause
+ }
+
+ /// Returns true if `E` is the type held by this error object.
+ ///
+ /// For errors with context, this method returns true if `E` matches the
+ /// type of the context `C` **or** the type of the error on which the
+ /// context has been attached. For details about the interaction between
+ /// context and downcasting, [see here].
+ ///
+ /// [see here]: trait.Context.html#effect-on-downcasting
+ pub fn is<E>(&self) -> bool
+ where
+ E: Display + Debug + Send + Sync + 'static,
+ {
+ self.downcast_ref::<E>().is_some()
+ }
+
+ /// Attempt to downcast the error object to a concrete type.
+ pub fn downcast<E>(self) -> Result<E, Self>
+ where
+ E: Display + Debug + Send + Sync + 'static,
+ {
+ let target = TypeId::of::<E>();
+ unsafe {
+ // Use vtable to find NonNull<()> which points to a value of type E
+ // somewhere inside the data structure.
+ let addr = match (self.inner.vtable.object_downcast)(&self.inner, target) {
+ Some(addr) => addr,
+ None => return Err(self),
+ };
+
+ // Prepare to read E out of the data structure. We'll drop the rest
+ // of the data structure separately so that E is not dropped.
+ let outer = ManuallyDrop::new(self);
+
+ // Read E from where the vtable found it.
+ let error = ptr::read(addr.cast::<E>().as_ptr());
+
+ // Read Box<ErrorImpl<()>> from self. Can't move it out because
+ // Error has a Drop impl which we want to not run.
+ let inner = ptr::read(&outer.inner);
+ let erased = ManuallyDrop::into_inner(inner);
+
+ // Drop rest of the data structure outside of E.
+ (erased.vtable.object_drop_rest)(erased, target);
+
+ Ok(error)
+ }
+ }
+
+ /// Downcast this error object by reference.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use anyhow::anyhow;
+ /// # use std::fmt::{self, Display};
+ /// # use std::task::Poll;
+ /// #
+ /// # #[derive(Debug)]
+ /// # enum DataStoreError {
+ /// # Censored(()),
+ /// # }
+ /// #
+ /// # impl Display for DataStoreError {
+ /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ /// # unimplemented!()
+ /// # }
+ /// # }
+ /// #
+ /// # impl std::error::Error for DataStoreError {}
+ /// #
+ /// # const REDACTED_CONTENT: () = ();
+ /// #
+ /// # let error = anyhow!("...");
+ /// # let root_cause = &error;
+ /// #
+ /// # let ret =
+ /// // If the error was caused by redaction, then return a tombstone instead
+ /// // of the content.
+ /// match root_cause.downcast_ref::<DataStoreError>() {
+ /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
+ /// None => Err(error),
+ /// }
+ /// # ;
+ /// ```
+ pub fn downcast_ref<E>(&self) -> Option<&E>
+ where
+ E: Display + Debug + Send + Sync + 'static,
+ {
+ let target = TypeId::of::<E>();
+ unsafe {
+ // Use vtable to find NonNull<()> which points to a value of type E
+ // somewhere inside the data structure.
+ let addr = (self.inner.vtable.object_downcast)(&self.inner, target)?;
+ Some(&*addr.cast::<E>().as_ptr())
+ }
+ }
+
+ /// Downcast this error object by mutable reference.
+ pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
+ where
+ E: Display + Debug + Send + Sync + 'static,
+ {
+ let target = TypeId::of::<E>();
+ unsafe {
+ // Use vtable to find NonNull<()> which points to a value of type E
+ // somewhere inside the data structure.
+ let addr = (self.inner.vtable.object_downcast)(&self.inner, target)?;
+ Some(&mut *addr.cast::<E>().as_ptr())
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<E> From<E> for Error
+where
+ E: StdError + Send + Sync + 'static,
+{
+ fn from(error: E) -> Self {
+ let backtrace = backtrace_if_absent!(error);
+ Error::from_std(error, backtrace)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Deref for Error {
+ type Target = dyn StdError + Send + Sync + 'static;
+
+ fn deref(&self) -> &Self::Target {
+ self.inner.error()
+ }
+}
+
+#[cfg(feature = "std")]
+impl DerefMut for Error {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ self.inner.error_mut()
+ }
+}
+
+impl Display for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.display(formatter)
+ }
+}
+
+impl Debug for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.debug(formatter)
+ }
+}
+
+impl Drop for Error {
+ fn drop(&mut self) {
+ unsafe {
+ // Read Box<ErrorImpl<()>> from self.
+ let inner = ptr::read(&self.inner);
+ let erased = ManuallyDrop::into_inner(inner);
+
+ // Invoke the vtable's drop behavior.
+ (erased.vtable.object_drop)(erased);
+ }
+ }
+}
+
+struct ErrorVTable {
+ object_drop: unsafe fn(Box<ErrorImpl<()>>),
+ object_ref: unsafe fn(&ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static),
+ #[cfg(feature = "std")]
+ object_mut: unsafe fn(&mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static),
+ object_boxed: unsafe fn(Box<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>,
+ object_downcast: unsafe fn(&ErrorImpl<()>, TypeId) -> Option<NonNull<()>>,
+ object_drop_rest: unsafe fn(Box<ErrorImpl<()>>, TypeId),
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_drop<E>(e: Box<ErrorImpl<()>>) {
+ // Cast back to ErrorImpl<E> so that the allocator receives the correct
+ // Layout to deallocate the Box's memory.
+ let unerased = mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<E>>>(e);
+ drop(unerased);
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_drop_front<E>(e: Box<ErrorImpl<()>>, target: TypeId) {
+ // Drop the fields of ErrorImpl other than E as well as the Box allocation,
+ // without dropping E itself. This is used by downcast after doing a
+ // ptr::read to take ownership of the E.
+ let _ = target;
+ let unerased = mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<ManuallyDrop<E>>>>(e);
+ drop(unerased);
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_ref<E>(e: &ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static)
+where
+ E: StdError + Send + Sync + 'static,
+{
+ // Attach E's native StdError vtable onto a pointer to self._object.
+ &(*(e as *const ErrorImpl<()> as *const ErrorImpl<E>))._object
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+#[cfg(feature = "std")]
+unsafe fn object_mut<E>(e: &mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static)
+where
+ E: StdError + Send + Sync + 'static,
+{
+ // Attach E's native StdError vtable onto a pointer to self._object.
+ &mut (*(e as *mut ErrorImpl<()> as *mut ErrorImpl<E>))._object
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_boxed<E>(e: Box<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>
+where
+ E: StdError + Send + Sync + 'static,
+{
+ // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
+ mem::transmute::<Box<ErrorImpl<()>>, Box<ErrorImpl<E>>>(e)
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_downcast<E>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
+where
+ E: 'static,
+{
+ if TypeId::of::<E>() == target {
+ // Caller is looking for an E pointer and e is ErrorImpl<E>, take a
+ // pointer to its E field.
+ let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<E>;
+ let addr = &(*unerased)._object as *const E as *mut ();
+ Some(NonNull::new_unchecked(addr))
+ } else {
+ None
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
+#[cfg(feature = "std")]
+unsafe fn context_downcast<C, E>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
+where
+ C: 'static,
+ E: 'static,
+{
+ if TypeId::of::<C>() == target {
+ let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<C, E>>;
+ let addr = &(*unerased)._object.context as *const C as *mut ();
+ Some(NonNull::new_unchecked(addr))
+ } else if TypeId::of::<E>() == target {
+ let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<C, E>>;
+ let addr = &(*unerased)._object.error as *const E as *mut ();
+ Some(NonNull::new_unchecked(addr))
+ } else {
+ None
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
+#[cfg(feature = "std")]
+unsafe fn context_drop_rest<C, E>(e: Box<ErrorImpl<()>>, target: TypeId)
+where
+ C: 'static,
+ E: 'static,
+{
+ // Called after downcasting by value to either the C or the E and doing a
+ // ptr::read to take ownership of that value.
+ if TypeId::of::<C>() == target {
+ let unerased = mem::transmute::<
+ Box<ErrorImpl<()>>,
+ Box<ErrorImpl<ContextError<ManuallyDrop<C>, E>>>,
+ >(e);
+ drop(unerased);
+ } else {
+ let unerased = mem::transmute::<
+ Box<ErrorImpl<()>>,
+ Box<ErrorImpl<ContextError<C, ManuallyDrop<E>>>>,
+ >(e);
+ drop(unerased);
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+unsafe fn context_chain_downcast<C>(e: &ErrorImpl<()>, target: TypeId) -> Option<NonNull<()>>
+where
+ C: 'static,
+{
+ if TypeId::of::<C>() == target {
+ let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<C, Error>>;
+ let addr = &(*unerased)._object.context as *const C as *mut ();
+ Some(NonNull::new_unchecked(addr))
+ } else {
+ // Recurse down the context chain per the inner error's vtable.
+ let unerased = e as *const ErrorImpl<()> as *const ErrorImpl<ContextError<C, Error>>;
+ let source = &(*unerased)._object.error;
+ (source.inner.vtable.object_downcast)(&source.inner, target)
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+unsafe fn context_chain_drop_rest<C>(e: Box<ErrorImpl<()>>, target: TypeId)
+where
+ C: 'static,
+{
+ // Called after downcasting by value to either the C or one of the causes
+ // and doing a ptr::read to take ownership of that value.
+ if TypeId::of::<C>() == target {
+ let unerased = mem::transmute::<
+ Box<ErrorImpl<()>>,
+ Box<ErrorImpl<ContextError<ManuallyDrop<C>, Error>>>,
+ >(e);
+ // Drop the entire rest of the data structure rooted in the next Error.
+ drop(unerased);
+ } else {
+ let unerased = mem::transmute::<
+ Box<ErrorImpl<()>>,
+ Box<ErrorImpl<ContextError<C, ManuallyDrop<Error>>>>,
+ >(e);
+ // Read out a ManuallyDrop<Box<ErrorImpl<()>>> from the next error.
+ let inner = ptr::read(&unerased._object.error.inner);
+ drop(unerased);
+ let erased = ManuallyDrop::into_inner(inner);
+ // Recursively drop the next error using the same target typeid.
+ (erased.vtable.object_drop_rest)(erased, target);
+ }
+}
+
+// repr C to ensure that E remains in the final position.
+#[repr(C)]
+pub(crate) struct ErrorImpl<E> {
+ vtable: &'static ErrorVTable,
+ backtrace: Option<Backtrace>,
+ // NOTE: Don't use directly. Use only through vtable. Erased type may have
+ // different alignment.
+ _object: E,
+}
+
+// repr C to ensure that ContextError<C, E> has the same layout as
+// ContextError<ManuallyDrop<C>, E> and ContextError<C, ManuallyDrop<E>>.
+#[repr(C)]
+pub(crate) struct ContextError<C, E> {
+ pub context: C,
+ pub error: E,
+}
+
+impl<E> ErrorImpl<E> {
+ fn erase(&self) -> &ErrorImpl<()> {
+ // Erase the concrete type of E but preserve the vtable in self.vtable
+ // for manipulating the resulting thin pointer. This is analogous to an
+ // unsize coersion.
+ unsafe { &*(self as *const ErrorImpl<E> as *const ErrorImpl<()>) }
+ }
+}
+
+impl ErrorImpl<()> {
+ pub(crate) fn error(&self) -> &(dyn StdError + Send + Sync + 'static) {
+ // Use vtable to attach E's native StdError vtable for the right
+ // original type E.
+ unsafe { &*(self.vtable.object_ref)(self) }
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
+ // Use vtable to attach E's native StdError vtable for the right
+ // original type E.
+ unsafe { &mut *(self.vtable.object_mut)(self) }
+ }
+
+ #[cfg(backtrace)]
+ pub(crate) fn backtrace(&self) -> &Backtrace {
+ // This unwrap can only panic if the underlying error's backtrace method
+ // is nondeterministic, which would only happen in maliciously
+ // constructed code.
+ self.backtrace
+ .as_ref()
+ .or_else(|| self.error().backtrace())
+ .expect("backtrace capture failed")
+ }
+
+ pub(crate) fn chain(&self) -> Chain {
+ Chain::new(self.error())
+ }
+}
+
+impl<E> StdError for ErrorImpl<E>
+where
+ E: StdError,
+{
+ #[cfg(backtrace)]
+ fn backtrace(&self) -> Option<&Backtrace> {
+ Some(self.erase().backtrace())
+ }
+
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ self.erase().error().source()
+ }
+}
+
+impl<E> Debug for ErrorImpl<E>
+where
+ E: Debug,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.erase().debug(formatter)
+ }
+}
+
+impl<E> Display for ErrorImpl<E>
+where
+ E: Display,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.erase().error(), formatter)
+ }
+}
+
+impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
+ fn from(error: Error) -> Self {
+ let outer = ManuallyDrop::new(error);
+ unsafe {
+ // Read Box<ErrorImpl<()>> from error. Can't move it out because
+ // Error has a Drop impl which we want to not run.
+ let inner = ptr::read(&outer.inner);
+ let erased = ManuallyDrop::into_inner(inner);
+
+ // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
+ // the right original type E.
+ (erased.vtable.object_boxed)(erased)
+ }
+ }
+}
+
+impl From<Error> for Box<dyn StdError + 'static> {
+ fn from(error: Error) -> Self {
+ Box::<dyn StdError + Send + Sync>::from(error)
+ }
+}
+
+#[cfg(feature = "std")]
+impl AsRef<dyn StdError + Send + Sync> for Error {
+ fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
+ &**self
+ }
+}
+
+#[cfg(feature = "std")]
+impl AsRef<dyn StdError> for Error {
+ fn as_ref(&self) -> &(dyn StdError + 'static) {
+ &**self
+ }
+}
diff --git a/third_party/rust/anyhow/src/fmt.rs b/third_party/rust/anyhow/src/fmt.rs
new file mode 100644
index 0000000000..16a82ba8d8
--- /dev/null
+++ b/third_party/rust/anyhow/src/fmt.rs
@@ -0,0 +1,149 @@
+use crate::chain::Chain;
+use crate::error::ErrorImpl;
+use core::fmt::{self, Debug, Write};
+
+impl ErrorImpl<()> {
+ pub(crate) fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.error())?;
+
+ if f.alternate() {
+ for cause in self.chain().skip(1) {
+ write!(f, ": {}", cause)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let error = self.error();
+
+ if f.alternate() {
+ return Debug::fmt(error, f);
+ }
+
+ write!(f, "{}", error)?;
+
+ if let Some(cause) = error.source() {
+ write!(f, "\n\nCaused by:")?;
+ let multiple = cause.source().is_some();
+ for (n, error) in Chain::new(cause).enumerate() {
+ writeln!(f)?;
+ let mut indented = Indented {
+ inner: f,
+ number: if multiple { Some(n) } else { None },
+ started: false,
+ };
+ write!(indented, "{}", error)?;
+ }
+ }
+
+ #[cfg(backtrace)]
+ {
+ use std::backtrace::BacktraceStatus;
+
+ let backtrace = self.backtrace();
+ if let BacktraceStatus::Captured = backtrace.status() {
+ let mut backtrace = backtrace.to_string();
+ if backtrace.starts_with("stack backtrace:") {
+ // Capitalize to match "Caused by:"
+ backtrace.replace_range(0..1, "S");
+ }
+ backtrace.truncate(backtrace.trim_end().len());
+ write!(f, "\n\n{}", backtrace)?;
+ }
+ }
+
+ Ok(())
+ }
+}
+
+struct Indented<'a, D> {
+ inner: &'a mut D,
+ number: Option<usize>,
+ started: bool,
+}
+
+impl<T> Write for Indented<'_, T>
+where
+ T: Write,
+{
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ for (i, line) in s.split('\n').enumerate() {
+ if !self.started {
+ self.started = true;
+ match self.number {
+ Some(number) => write!(self.inner, "{: >5}: ", number)?,
+ None => self.inner.write_str(" ")?,
+ }
+ } else if i > 0 {
+ self.inner.write_char('\n')?;
+ if self.number.is_some() {
+ self.inner.write_str(" ")?;
+ } else {
+ self.inner.write_str(" ")?;
+ }
+ }
+
+ self.inner.write_str(line)?;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn one_digit() {
+ let input = "verify\nthis";
+ let expected = " 2: verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: Some(2),
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn two_digits() {
+ let input = "verify\nthis";
+ let expected = " 12: verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: Some(12),
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn no_digits() {
+ let input = "verify\nthis";
+ let expected = " verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: None,
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+}
diff --git a/third_party/rust/anyhow/src/kind.rs b/third_party/rust/anyhow/src/kind.rs
new file mode 100644
index 0000000000..fdeb060ad8
--- /dev/null
+++ b/third_party/rust/anyhow/src/kind.rs
@@ -0,0 +1,116 @@
+// Tagged dispatch mechanism for resolving the behavior of `anyhow!($expr)`.
+//
+// When anyhow! is given a single expr argument to turn into anyhow::Error, we
+// want the resulting Error to pick up the input's implementation of source()
+// and backtrace() if it has a std::error::Error impl, otherwise require nothing
+// more than Display and Debug.
+//
+// Expressed in terms of specialization, we want something like:
+//
+// trait AnyhowNew {
+// fn new(self) -> Error;
+// }
+//
+// impl<T> AnyhowNew for T
+// where
+// T: Display + Debug + Send + Sync + 'static,
+// {
+// default fn new(self) -> Error {
+// /* no std error impl */
+// }
+// }
+//
+// impl<T> AnyhowNew for T
+// where
+// T: std::error::Error + Send + Sync + 'static,
+// {
+// fn new(self) -> Error {
+// /* use std error's source() and backtrace() */
+// }
+// }
+//
+// Since specialization is not stable yet, instead we rely on autoref behavior
+// of method resolution to perform tagged dispatch. Here we have two traits
+// AdhocKind and TraitKind that both have an anyhow_kind() method. AdhocKind is
+// implemented whether or not the caller's type has a std error impl, while
+// TraitKind is implemented only when a std error impl does exist. The ambiguity
+// is resolved by AdhocKind requiring an extra autoref so that it has lower
+// precedence.
+//
+// The anyhow! macro will set up the call in this form:
+//
+// #[allow(unused_imports)]
+// use $crate::private::{AdhocKind, TraitKind};
+// let error = $msg;
+// (&error).anyhow_kind().new(error)
+
+use crate::Error;
+use core::fmt::{Debug, Display};
+
+#[cfg(feature = "std")]
+use crate::StdError;
+
+#[cfg(backtrace)]
+use std::backtrace::Backtrace;
+
+pub struct Adhoc;
+
+pub trait AdhocKind: Sized {
+ #[inline]
+ fn anyhow_kind(&self) -> Adhoc {
+ Adhoc
+ }
+}
+
+impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {}
+
+impl Adhoc {
+ pub fn new<M>(self, message: M) -> Error
+ where
+ M: Display + Debug + Send + Sync + 'static,
+ {
+ Error::from_adhoc(message, backtrace!())
+ }
+}
+
+pub struct Trait;
+
+pub trait TraitKind: Sized {
+ #[inline]
+ fn anyhow_kind(&self) -> Trait {
+ Trait
+ }
+}
+
+impl<E> TraitKind for E where E: Into<Error> {}
+
+impl Trait {
+ pub fn new<E>(self, error: E) -> Error
+ where
+ E: Into<Error>,
+ {
+ error.into()
+ }
+}
+
+#[cfg(feature = "std")]
+pub struct Boxed;
+
+#[cfg(feature = "std")]
+pub trait BoxedKind: Sized {
+ #[inline]
+ fn anyhow_kind(&self) -> Boxed {
+ Boxed
+ }
+}
+
+#[cfg(feature = "std")]
+impl BoxedKind for Box<dyn StdError + Send + Sync> {}
+
+#[cfg(feature = "std")]
+impl Boxed {
+ pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Error {
+ let backtrace = backtrace_if_absent!(error);
+ Error::from_boxed(error, backtrace)
+ }
+}
diff --git a/third_party/rust/anyhow/src/lib.rs b/third_party/rust/anyhow/src/lib.rs
new file mode 100644
index 0000000000..91d4c4652e
--- /dev/null
+++ b/third_party/rust/anyhow/src/lib.rs
@@ -0,0 +1,603 @@
+//! [![github]](https://github.com/dtolnay/anyhow)&ensp;[![crates-io]](https://crates.io/crates/anyhow)&ensp;[![docs-rs]](https://docs.rs/anyhow)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//!
+//! <br>
+//!
+//! This library provides [`anyhow::Error`][Error], a trait object based error
+//! type for easy idiomatic error handling in Rust applications.
+//!
+//! <br>
+//!
+//! # Details
+//!
+//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as
+//! the return type of any fallible function.
+//!
+//! Within the function, use `?` to easily propagate any error that implements
+//! the `std::error::Error` trait.
+//!
+//! ```
+//! # pub trait Deserialize {}
+//! #
+//! # mod serde_json {
+//! # use super::Deserialize;
+//! # use std::io;
+//! #
+//! # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
+//! # unimplemented!()
+//! # }
+//! # }
+//! #
+//! # struct ClusterMap;
+//! #
+//! # impl Deserialize for ClusterMap {}
+//! #
+//! use anyhow::Result;
+//!
+//! fn get_cluster_info() -> Result<ClusterMap> {
+//! let config = std::fs::read_to_string("cluster.json")?;
+//! let map: ClusterMap = serde_json::from_str(&config)?;
+//! Ok(map)
+//! }
+//! #
+//! # fn main() {}
+//! ```
+//!
+//! - Attach context to help the person troubleshooting the error understand
+//! where things went wrong. A low-level error like "No such file or
+//! directory" can be annoying to debug without more context about what higher
+//! level step the application was in the middle of.
+//!
+//! ```
+//! # struct It;
+//! #
+//! # impl It {
+//! # fn detach(&self) -> Result<()> {
+//! # unimplemented!()
+//! # }
+//! # }
+//! #
+//! use anyhow::{Context, Result};
+//!
+//! fn main() -> Result<()> {
+//! # return Ok(());
+//! #
+//! # const _: &str = stringify! {
+//! ...
+//! # };
+//! #
+//! # let it = It;
+//! # let path = "./path/to/instrs.json";
+//! #
+//! it.detach().context("Failed to detach the important thing")?;
+//!
+//! let content = std::fs::read(path)
+//! .with_context(|| format!("Failed to read instrs from {}", path))?;
+//! #
+//! # const _: &str = stringify! {
+//! ...
+//! # };
+//! #
+//! # Ok(())
+//! }
+//! ```
+//!
+//! ```console
+//! Error: Failed to read instrs from ./path/to/instrs.json
+//!
+//! Caused by:
+//! No such file or directory (os error 2)
+//! ```
+//!
+//! - Downcasting is supported and can be by value, by shared reference, or by
+//! mutable reference as needed.
+//!
+//! ```
+//! # use anyhow::anyhow;
+//! # use std::fmt::{self, Display};
+//! # use std::task::Poll;
+//! #
+//! # #[derive(Debug)]
+//! # enum DataStoreError {
+//! # Censored(()),
+//! # }
+//! #
+//! # impl Display for DataStoreError {
+//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+//! # unimplemented!()
+//! # }
+//! # }
+//! #
+//! # impl std::error::Error for DataStoreError {}
+//! #
+//! # const REDACTED_CONTENT: () = ();
+//! #
+//! # let error = anyhow!("...");
+//! # let root_cause = &error;
+//! #
+//! # let ret =
+//! // If the error was caused by redaction, then return a
+//! // tombstone instead of the content.
+//! match root_cause.downcast_ref::<DataStoreError>() {
+//! Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
+//! None => Err(error),
+//! }
+//! # ;
+//! ```
+//!
+//! - If using the nightly channel, a backtrace is captured and printed with the
+//! error if the underlying error type does not already provide its own. In
+//! order to see backtraces, they must be enabled through the environment
+//! variables described in [`std::backtrace`]:
+//!
+//! - If you want panics and errors to both have backtraces, set
+//! `RUST_BACKTRACE=1`;
+//! - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
+//! - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
+//! `RUST_LIB_BACKTRACE=0`.
+//!
+//! The tracking issue for this feature is [rust-lang/rust#53487].
+//!
+//! [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
+//! [rust-lang/rust#53487]: https://github.com/rust-lang/rust/issues/53487
+//!
+//! - Anyhow works with any error type that has an impl of `std::error::Error`,
+//! including ones defined in your crate. We do not bundle a `derive(Error)`
+//! macro but you can write the impls yourself or use a standalone macro like
+//! [thiserror].
+//!
+//! [thiserror]: https://github.com/dtolnay/thiserror
+//!
+//! ```
+//! use thiserror::Error;
+//!
+//! #[derive(Error, Debug)]
+//! pub enum FormatError {
+//! #[error("Invalid header (expected {expected:?}, got {found:?})")]
+//! InvalidHeader {
+//! expected: String,
+//! found: String,
+//! },
+//! #[error("Missing attribute: {0}")]
+//! MissingAttribute(String),
+//! }
+//! ```
+//!
+//! - One-off error messages can be constructed using the `anyhow!` macro, which
+//! supports string interpolation and produces an `anyhow::Error`.
+//!
+//! ```
+//! # use anyhow::{anyhow, Result};
+//! #
+//! # fn demo() -> Result<()> {
+//! # let missing = "...";
+//! return Err(anyhow!("Missing attribute: {}", missing));
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! <br>
+//!
+//! # No-std support
+//!
+//! In no_std mode, the same API is almost all available and works the same way.
+//! To depend on Anyhow in no_std mode, disable our default enabled "std"
+//! feature in Cargo.toml. A global allocator is required.
+//!
+//! ```toml
+//! [dependencies]
+//! anyhow = { version = "1.0", default-features = false }
+//! ```
+//!
+//! Since the `?`-based error conversions would normally rely on the
+//! `std::error::Error` trait which is only available through std, no_std mode
+//! will require an explicit `.map_err(Error::msg)` when working with a
+//! non-Anyhow error type inside a function that returns Anyhow's error type.
+
+#![doc(html_root_url = "https://docs.rs/anyhow/1.0.30")]
+#![cfg_attr(backtrace, feature(backtrace))]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![allow(
+ clippy::needless_doctest_main,
+ clippy::new_ret_no_self,
+ clippy::wrong_self_convention
+)]
+
+mod alloc {
+ #[cfg(not(feature = "std"))]
+ extern crate alloc;
+
+ #[cfg(not(feature = "std"))]
+ pub use alloc::boxed::Box;
+
+ #[cfg(feature = "std")]
+ pub use std::boxed::Box;
+}
+
+#[macro_use]
+mod backtrace;
+mod chain;
+mod context;
+mod error;
+mod fmt;
+mod kind;
+mod macros;
+mod wrapper;
+
+use crate::alloc::Box;
+use crate::error::ErrorImpl;
+use core::fmt::Display;
+use core::mem::ManuallyDrop;
+
+#[cfg(not(feature = "std"))]
+use core::fmt::Debug;
+
+#[cfg(feature = "std")]
+use std::error::Error as StdError;
+
+#[cfg(not(feature = "std"))]
+trait StdError: Debug + Display {
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ None
+ }
+}
+
+pub use anyhow as format_err;
+
+/// The `Error` type, a wrapper around a dynamic error type.
+///
+/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these
+/// differences:
+///
+/// - `Error` requires that the error is `Send`, `Sync`, and `'static`.
+/// - `Error` guarantees that a backtrace is available, even if the underlying
+/// error type does not provide one.
+/// - `Error` is represented as a narrow pointer &mdash; exactly one word in
+/// size instead of two.
+///
+/// <br>
+///
+/// # Display representations
+///
+/// When you print an error object using "{}" or to_string(), only the outermost
+/// underlying error or context is printed, not any of the lower level causes.
+/// This is exactly as if you had called the Display impl of the error from
+/// which you constructed your anyhow::Error.
+///
+/// ```console
+/// Failed to read instrs from ./path/to/instrs.json
+/// ```
+///
+/// To print causes as well using anyhow's default formatting of causes, use the
+/// alternate selector "{:#}".
+///
+/// ```console
+/// Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2)
+/// ```
+///
+/// The Debug format "{:?}" includes your backtrace if one was captured. Note
+/// that this is the representation you get by default if you return an error
+/// from `fn main` instead of printing it explicitly yourself.
+///
+/// ```console
+/// Error: Failed to read instrs from ./path/to/instrs.json
+///
+/// Caused by:
+/// No such file or directory (os error 2)
+///
+/// Stack backtrace:
+/// 0: <E as anyhow::context::ext::StdError>::ext_context
+/// at /git/anyhow/src/backtrace.rs:26
+/// 1: core::result::Result<T,E>::map_err
+/// at /git/rustc/src/libcore/result.rs:596
+/// 2: anyhow::context::<impl anyhow::Context<T,E> for core::result::Result<T,E>>::with_context
+/// at /git/anyhow/src/context.rs:58
+/// 3: testing::main
+/// at src/main.rs:5
+/// 4: std::rt::lang_start
+/// at /git/rustc/src/libstd/rt.rs:61
+/// 5: main
+/// 6: __libc_start_main
+/// 7: _start
+/// ```
+///
+/// To see a conventional struct-style Debug representation, use "{:#?}".
+///
+/// ```console
+/// Error {
+/// context: "Failed to read instrs from ./path/to/instrs.json",
+/// source: Os {
+/// code: 2,
+/// kind: NotFound,
+/// message: "No such file or directory",
+/// },
+/// }
+/// ```
+///
+/// If none of the built-in representations are appropriate and you would prefer
+/// to render the error and its cause chain yourself, it can be done something
+/// like this:
+///
+/// ```
+/// use anyhow::{Context, Result};
+///
+/// fn main() {
+/// if let Err(err) = try_main() {
+/// eprintln!("ERROR: {}", err);
+/// err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause));
+/// std::process::exit(1);
+/// }
+/// }
+///
+/// fn try_main() -> Result<()> {
+/// # const IGNORE: &str = stringify! {
+/// ...
+/// # };
+/// # Ok(())
+/// }
+/// ```
+pub struct Error {
+ inner: ManuallyDrop<Box<ErrorImpl<()>>>,
+}
+
+/// Iterator of a chain of source errors.
+///
+/// This type is the iterator returned by [`Error::chain`].
+///
+/// # Example
+///
+/// ```
+/// use anyhow::Error;
+/// use std::io;
+///
+/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> {
+/// for cause in error.chain() {
+/// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
+/// return Some(io_error.kind());
+/// }
+/// }
+/// None
+/// }
+/// ```
+#[cfg(feature = "std")]
+#[derive(Clone)]
+pub struct Chain<'a> {
+ state: crate::chain::ChainState<'a>,
+}
+
+/// `Result<T, Error>`
+///
+/// This is a reasonable return type to use throughout your application but also
+/// for `fn main`; if you do, failures will be printed along with any
+/// [context][Context] and a backtrace if one was captured.
+///
+/// `anyhow::Result` may be used with one *or* two type parameters.
+///
+/// ```rust
+/// use anyhow::Result;
+///
+/// # const IGNORE: &str = stringify! {
+/// fn demo1() -> Result<T> {...}
+/// // ^ equivalent to std::result::Result<T, anyhow::Error>
+///
+/// fn demo2() -> Result<T, OtherError> {...}
+/// // ^ equivalent to std::result::Result<T, OtherError>
+/// # };
+/// ```
+///
+/// # Example
+///
+/// ```
+/// # pub trait Deserialize {}
+/// #
+/// # mod serde_json {
+/// # use super::Deserialize;
+/// # use std::io;
+/// #
+/// # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {
+/// # unimplemented!()
+/// # }
+/// # }
+/// #
+/// # #[derive(Debug)]
+/// # struct ClusterMap;
+/// #
+/// # impl Deserialize for ClusterMap {}
+/// #
+/// use anyhow::Result;
+///
+/// fn main() -> Result<()> {
+/// # return Ok(());
+/// let config = std::fs::read_to_string("cluster.json")?;
+/// let map: ClusterMap = serde_json::from_str(&config)?;
+/// println!("cluster info: {:#?}", map);
+/// Ok(())
+/// }
+/// ```
+pub type Result<T, E = Error> = core::result::Result<T, E>;
+
+/// Provides the `context` method for `Result`.
+///
+/// This trait is sealed and cannot be implemented for types outside of
+/// `anyhow`.
+///
+/// <br>
+///
+/// # Example
+///
+/// ```
+/// use anyhow::{Context, Result};
+/// use std::fs;
+/// use std::path::PathBuf;
+///
+/// pub struct ImportantThing {
+/// path: PathBuf,
+/// }
+///
+/// impl ImportantThing {
+/// # const IGNORE: &'static str = stringify! {
+/// pub fn detach(&mut self) -> Result<()> {...}
+/// # };
+/// # fn detach(&mut self) -> Result<()> {
+/// # unimplemented!()
+/// # }
+/// }
+///
+/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> {
+/// it.detach().context("Failed to detach the important thing")?;
+///
+/// let path = &it.path;
+/// let content = fs::read(path)
+/// .with_context(|| format!("Failed to read instrs from {}", path.display()))?;
+///
+/// Ok(content)
+/// }
+/// ```
+///
+/// When printed, the outermost context would be printed first and the lower
+/// level underlying causes would be enumerated below.
+///
+/// ```console
+/// Error: Failed to read instrs from ./path/to/instrs.json
+///
+/// Caused by:
+/// No such file or directory (os error 2)
+/// ```
+///
+/// <br>
+///
+/// # Effect on downcasting
+///
+/// After attaching context of type `C` onto an error of type `E`, the resulting
+/// `anyhow::Error` may be downcast to `C` **or** to `E`.
+///
+/// That is, in codebases that rely on downcasting, Anyhow's context supports
+/// both of the following use cases:
+///
+/// - **Attaching context whose type is insignificant onto errors whose type
+/// is used in downcasts.**
+///
+/// In other error libraries whose context is not designed this way, it can
+/// be risky to introduce context to existing code because new context might
+/// break existing working downcasts. In Anyhow, any downcast that worked
+/// before adding context will continue to work after you add a context, so
+/// you should freely add human-readable context to errors wherever it would
+/// be helpful.
+///
+/// ```
+/// # use anyhow::bail;
+/// # use thiserror::Error;
+/// #
+/// # #[derive(Error, Debug)]
+/// # #[error("???")]
+/// # struct SuspiciousError;
+/// #
+/// # fn helper() -> Result<()> {
+/// # bail!(SuspiciousError);
+/// # }
+/// #
+/// use anyhow::{Context, Result};
+///
+/// fn do_it() -> Result<()> {
+/// helper().context("Failed to complete the work")?;
+/// # const IGNORE: &str = stringify! {
+/// ...
+/// # };
+/// # unreachable!()
+/// }
+///
+/// fn main() {
+/// let err = do_it().unwrap_err();
+/// if let Some(e) = err.downcast_ref::<SuspiciousError>() {
+/// // If helper() returned SuspiciousError, this downcast will
+/// // correctly succeed even with the context in between.
+/// # return;
+/// }
+/// # panic!("expected downcast to succeed");
+/// }
+/// ```
+///
+/// - **Attaching context whose type is used in downcasts onto errors whose
+/// type is insignificant.**
+///
+/// Some codebases prefer to use machine-readable context to categorize
+/// lower level errors in a way that will be actionable to higher levels of
+/// the application.
+///
+/// ```
+/// # use anyhow::bail;
+/// # use thiserror::Error;
+/// #
+/// # #[derive(Error, Debug)]
+/// # #[error("???")]
+/// # struct HelperFailed;
+/// #
+/// # fn helper() -> Result<()> {
+/// # bail!("no such file or directory");
+/// # }
+/// #
+/// use anyhow::{Context, Result};
+///
+/// fn do_it() -> Result<()> {
+/// helper().context(HelperFailed)?;
+/// # const IGNORE: &str = stringify! {
+/// ...
+/// # };
+/// # unreachable!()
+/// }
+///
+/// fn main() {
+/// let err = do_it().unwrap_err();
+/// if let Some(e) = err.downcast_ref::<HelperFailed>() {
+/// // If helper failed, this downcast will succeed because
+/// // HelperFailed is the context that has been attached to
+/// // that error.
+/// # return;
+/// }
+/// # panic!("expected downcast to succeed");
+/// }
+/// ```
+pub trait Context<T, E>: context::private::Sealed {
+ /// Wrap the error value with additional context.
+ fn context<C>(self, context: C) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static;
+
+ /// Wrap the error value with additional context that is evaluated lazily
+ /// only once an error does occur.
+ fn with_context<C, F>(self, f: F) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ F: FnOnce() -> C;
+}
+
+// Not public API. Referenced by macro-generated code.
+#[doc(hidden)]
+pub mod private {
+ use crate::Error;
+ use core::fmt::{Debug, Display};
+
+ #[cfg(backtrace)]
+ use std::backtrace::Backtrace;
+
+ pub use core::result::Result::Err;
+
+ #[doc(hidden)]
+ pub mod kind {
+ pub use crate::kind::{AdhocKind, TraitKind};
+
+ #[cfg(feature = "std")]
+ pub use crate::kind::BoxedKind;
+ }
+
+ pub fn new_adhoc<M>(message: M) -> Error
+ where
+ M: Display + Debug + Send + Sync + 'static,
+ {
+ Error::from_adhoc(message, backtrace!())
+ }
+}
diff --git a/third_party/rust/anyhow/src/macros.rs b/third_party/rust/anyhow/src/macros.rs
new file mode 100644
index 0000000000..15a920810c
--- /dev/null
+++ b/third_party/rust/anyhow/src/macros.rs
@@ -0,0 +1,163 @@
+/// Return early with an error.
+///
+/// This macro is equivalent to `return Err(From::from($err))`.
+///
+/// # Example
+///
+/// ```
+/// # use anyhow::{bail, Result};
+/// #
+/// # fn has_permission(user: usize, resource: usize) -> bool {
+/// # true
+/// # }
+/// #
+/// # fn main() -> Result<()> {
+/// # let user = 0;
+/// # let resource = 0;
+/// #
+/// if !has_permission(user, resource) {
+/// bail!("permission denied for accessing {}", resource);
+/// }
+/// # Ok(())
+/// # }
+/// ```
+///
+/// ```
+/// # use anyhow::{bail, Result};
+/// # use thiserror::Error;
+/// #
+/// # const MAX_DEPTH: usize = 1;
+/// #
+/// #[derive(Error, Debug)]
+/// enum ScienceError {
+/// #[error("recursion limit exceeded")]
+/// RecursionLimitExceeded,
+/// # #[error("...")]
+/// # More = (stringify! {
+/// ...
+/// # }, 1).1,
+/// }
+///
+/// # fn main() -> Result<()> {
+/// # let depth = 0;
+/// #
+/// if depth > MAX_DEPTH {
+/// bail!(ScienceError::RecursionLimitExceeded);
+/// }
+/// # Ok(())
+/// # }
+/// ```
+#[macro_export]
+macro_rules! bail {
+ ($msg:literal $(,)?) => {
+ return $crate::private::Err($crate::anyhow!($msg));
+ };
+ ($err:expr $(,)?) => {
+ return $crate::private::Err($crate::anyhow!($err));
+ };
+ ($fmt:expr, $($arg:tt)*) => {
+ return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
+ };
+}
+
+/// Return early with an error if a condition is not satisfied.
+///
+/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
+///
+/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
+/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
+/// rather than panicking.
+///
+/// # Example
+///
+/// ```
+/// # use anyhow::{ensure, Result};
+/// #
+/// # fn main() -> Result<()> {
+/// # let user = 0;
+/// #
+/// ensure!(user == 0, "only user 0 is allowed");
+/// # Ok(())
+/// # }
+/// ```
+///
+/// ```
+/// # use anyhow::{ensure, Result};
+/// # use thiserror::Error;
+/// #
+/// # const MAX_DEPTH: usize = 1;
+/// #
+/// #[derive(Error, Debug)]
+/// enum ScienceError {
+/// #[error("recursion limit exceeded")]
+/// RecursionLimitExceeded,
+/// # #[error("...")]
+/// # More = (stringify! {
+/// ...
+/// # }, 1).1,
+/// }
+///
+/// # fn main() -> Result<()> {
+/// # let depth = 0;
+/// #
+/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
+/// # Ok(())
+/// # }
+/// ```
+#[macro_export]
+macro_rules! ensure {
+ ($cond:expr, $msg:literal $(,)?) => {
+ if !$cond {
+ return $crate::private::Err($crate::anyhow!($msg));
+ }
+ };
+ ($cond:expr, $err:expr $(,)?) => {
+ if !$cond {
+ return $crate::private::Err($crate::anyhow!($err));
+ }
+ };
+ ($cond:expr, $fmt:expr, $($arg:tt)*) => {
+ if !$cond {
+ return $crate::private::Err($crate::anyhow!($fmt, $($arg)*));
+ }
+ };
+}
+
+/// Construct an ad-hoc error from a string.
+///
+/// This evaluates to an `Error`. It can take either just a string, or a format
+/// string with arguments. It also can take any custom type which implements
+/// `Debug` and `Display`.
+///
+/// # Example
+///
+/// ```
+/// # type V = ();
+/// #
+/// use anyhow::{anyhow, Result};
+///
+/// fn lookup(key: &str) -> Result<V> {
+/// if key.len() != 16 {
+/// return Err(anyhow!("key length must be 16 characters, got {:?}", key));
+/// }
+///
+/// // ...
+/// # Ok(())
+/// }
+/// ```
+#[macro_export]
+macro_rules! anyhow {
+ ($msg:literal $(,)?) => {
+ // Handle $:literal as a special case to make cargo-expanded code more
+ // concise in the common case.
+ $crate::private::new_adhoc($msg)
+ };
+ ($err:expr $(,)?) => ({
+ use $crate::private::kind::*;
+ let error = $err;
+ (&error).anyhow_kind().new(error)
+ });
+ ($fmt:expr, $($arg:tt)*) => {
+ $crate::private::new_adhoc(format!($fmt, $($arg)*))
+ };
+}
diff --git a/third_party/rust/anyhow/src/wrapper.rs b/third_party/rust/anyhow/src/wrapper.rs
new file mode 100644
index 0000000000..3ebe51a883
--- /dev/null
+++ b/third_party/rust/anyhow/src/wrapper.rs
@@ -0,0 +1,78 @@
+use crate::StdError;
+use core::fmt::{self, Debug, Display};
+
+#[repr(transparent)]
+pub struct MessageError<M>(pub M);
+
+impl<M> Debug for MessageError<M>
+where
+ M: Display + Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.0, f)
+ }
+}
+
+impl<M> Display for MessageError<M>
+where
+ M: Display + Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
+impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}
+
+#[repr(transparent)]
+pub struct DisplayError<M>(pub M);
+
+impl<M> Debug for DisplayError<M>
+where
+ M: Display,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
+impl<M> Display for DisplayError<M>
+where
+ M: Display,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
+impl<M> StdError for DisplayError<M> where M: Display + 'static {}
+
+#[cfg(feature = "std")]
+#[repr(transparent)]
+pub struct BoxedError(pub Box<dyn StdError + Send + Sync>);
+
+#[cfg(feature = "std")]
+impl Debug for BoxedError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.0, f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl Display for BoxedError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
+#[cfg(feature = "std")]
+impl StdError for BoxedError {
+ #[cfg(backtrace)]
+ fn backtrace(&self) -> Option<&crate::backtrace::Backtrace> {
+ self.0.backtrace()
+ }
+
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ self.0.source()
+ }
+}
diff --git a/third_party/rust/anyhow/tests/common/mod.rs b/third_party/rust/anyhow/tests/common/mod.rs
new file mode 100644
index 0000000000..fc165a5be9
--- /dev/null
+++ b/third_party/rust/anyhow/tests/common/mod.rs
@@ -0,0 +1,14 @@
+use anyhow::{bail, Result};
+use std::io;
+
+pub fn bail_literal() -> Result<()> {
+ bail!("oh no!");
+}
+
+pub fn bail_fmt() -> Result<()> {
+ bail!("{} {}!", "oh", "no");
+}
+
+pub fn bail_error() -> Result<()> {
+ bail!(io::Error::new(io::ErrorKind::Other, "oh no!"));
+}
diff --git a/third_party/rust/anyhow/tests/compiletest.rs b/third_party/rust/anyhow/tests/compiletest.rs
new file mode 100644
index 0000000000..f9aea23b51
--- /dev/null
+++ b/third_party/rust/anyhow/tests/compiletest.rs
@@ -0,0 +1,6 @@
+#[rustversion::attr(not(nightly), ignore)]
+#[test]
+fn ui() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/*.rs");
+}
diff --git a/third_party/rust/anyhow/tests/drop/mod.rs b/third_party/rust/anyhow/tests/drop/mod.rs
new file mode 100644
index 0000000000..c9d7144479
--- /dev/null
+++ b/third_party/rust/anyhow/tests/drop/mod.rs
@@ -0,0 +1,52 @@
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::sync::atomic::AtomicBool;
+use std::sync::atomic::Ordering::SeqCst;
+use std::sync::Arc;
+
+#[derive(Debug)]
+pub struct Flag {
+ atomic: Arc<AtomicBool>,
+}
+
+impl Flag {
+ pub fn new() -> Self {
+ Flag {
+ atomic: Arc::new(AtomicBool::new(false)),
+ }
+ }
+
+ pub fn get(&self) -> bool {
+ self.atomic.load(SeqCst)
+ }
+}
+
+#[derive(Debug)]
+pub struct DetectDrop {
+ has_dropped: Flag,
+}
+
+impl DetectDrop {
+ pub fn new(has_dropped: &Flag) -> Self {
+ DetectDrop {
+ has_dropped: Flag {
+ atomic: Arc::clone(&has_dropped.atomic),
+ },
+ }
+ }
+}
+
+impl StdError for DetectDrop {}
+
+impl Display for DetectDrop {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "oh no!")
+ }
+}
+
+impl Drop for DetectDrop {
+ fn drop(&mut self) {
+ let already_dropped = self.has_dropped.atomic.swap(true, SeqCst);
+ assert!(!already_dropped);
+ }
+}
diff --git a/third_party/rust/anyhow/tests/test_autotrait.rs b/third_party/rust/anyhow/tests/test_autotrait.rs
new file mode 100644
index 0000000000..0c9326dad6
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_autotrait.rs
@@ -0,0 +1,13 @@
+use anyhow::Error;
+
+#[test]
+fn test_send() {
+ fn assert_send<T: Send>() {}
+ assert_send::<Error>();
+}
+
+#[test]
+fn test_sync() {
+ fn assert_sync<T: Sync>() {}
+ assert_sync::<Error>();
+}
diff --git a/third_party/rust/anyhow/tests/test_backtrace.rs b/third_party/rust/anyhow/tests/test_backtrace.rs
new file mode 100644
index 0000000000..ce385f5011
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_backtrace.rs
@@ -0,0 +1,13 @@
+#[rustversion::not(nightly)]
+#[ignore]
+#[test]
+fn test_backtrace() {}
+
+#[rustversion::nightly]
+#[test]
+fn test_backtrace() {
+ use anyhow::anyhow;
+
+ let error = anyhow!("oh no!");
+ let _ = error.backtrace();
+}
diff --git a/third_party/rust/anyhow/tests/test_boxed.rs b/third_party/rust/anyhow/tests/test_boxed.rs
new file mode 100644
index 0000000000..38a568fb73
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_boxed.rs
@@ -0,0 +1,40 @@
+use anyhow::anyhow;
+use std::error::Error as StdError;
+use std::io;
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+#[error("outer")]
+struct MyError {
+ source: io::Error,
+}
+
+#[test]
+fn test_boxed_str() {
+ let error = Box::<dyn StdError + Send + Sync>::from("oh no!");
+ let error = anyhow!(error);
+ assert_eq!("oh no!", error.to_string());
+ assert_eq!(
+ "oh no!",
+ error
+ .downcast_ref::<Box<dyn StdError + Send + Sync>>()
+ .unwrap()
+ .to_string()
+ );
+}
+
+#[test]
+fn test_boxed_thiserror() {
+ let error = MyError {
+ source: io::Error::new(io::ErrorKind::Other, "oh no!"),
+ };
+ let error = anyhow!(error);
+ assert_eq!("oh no!", error.source().unwrap().to_string());
+}
+
+#[test]
+fn test_boxed_anyhow() {
+ let error = anyhow!("oh no!").context("it failed");
+ let error = anyhow!(error);
+ assert_eq!("oh no!", error.source().unwrap().to_string());
+}
diff --git a/third_party/rust/anyhow/tests/test_chain.rs b/third_party/rust/anyhow/tests/test_chain.rs
new file mode 100644
index 0000000000..b1c5a3daaa
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_chain.rs
@@ -0,0 +1,45 @@
+use anyhow::{anyhow, Error};
+
+fn error() -> Error {
+ anyhow!(0).context(1).context(2).context(3)
+}
+
+#[test]
+fn test_iter() {
+ let e = error();
+ let mut chain = e.chain();
+ assert_eq!("3", chain.next().unwrap().to_string());
+ assert_eq!("2", chain.next().unwrap().to_string());
+ assert_eq!("1", chain.next().unwrap().to_string());
+ assert_eq!("0", chain.next().unwrap().to_string());
+ assert!(chain.next().is_none());
+ assert!(chain.next_back().is_none());
+}
+
+#[test]
+fn test_rev() {
+ let e = error();
+ let mut chain = e.chain().rev();
+ assert_eq!("0", chain.next().unwrap().to_string());
+ assert_eq!("1", chain.next().unwrap().to_string());
+ assert_eq!("2", chain.next().unwrap().to_string());
+ assert_eq!("3", chain.next().unwrap().to_string());
+ assert!(chain.next().is_none());
+ assert!(chain.next_back().is_none());
+}
+
+#[test]
+fn test_len() {
+ let e = error();
+ let mut chain = e.chain();
+ assert_eq!(4, chain.len());
+ assert_eq!("3", chain.next().unwrap().to_string());
+ assert_eq!(3, chain.len());
+ assert_eq!("0", chain.next_back().unwrap().to_string());
+ assert_eq!(2, chain.len());
+ assert_eq!("2", chain.next().unwrap().to_string());
+ assert_eq!(1, chain.len());
+ assert_eq!("1", chain.next_back().unwrap().to_string());
+ assert_eq!(0, chain.len());
+ assert!(chain.next().is_none());
+}
diff --git a/third_party/rust/anyhow/tests/test_context.rs b/third_party/rust/anyhow/tests/test_context.rs
new file mode 100644
index 0000000000..44c1c7036e
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_context.rs
@@ -0,0 +1,159 @@
+mod drop;
+
+use crate::drop::{DetectDrop, Flag};
+use anyhow::{Context, Error, Result};
+use std::fmt::{self, Display};
+use thiserror::Error;
+
+// https://github.com/dtolnay/anyhow/issues/18
+#[test]
+fn test_inference() -> Result<()> {
+ let x = "1";
+ let y: u32 = x.parse().context("...")?;
+ assert_eq!(y, 1);
+ Ok(())
+}
+
+macro_rules! context_type {
+ ($name:ident) => {
+ #[derive(Debug)]
+ struct $name {
+ message: &'static str,
+ drop: DetectDrop,
+ }
+
+ impl Display for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(self.message)
+ }
+ }
+ };
+}
+
+context_type!(HighLevel);
+context_type!(MidLevel);
+
+#[derive(Error, Debug)]
+#[error("{message}")]
+struct LowLevel {
+ message: &'static str,
+ drop: DetectDrop,
+}
+
+struct Dropped {
+ low: Flag,
+ mid: Flag,
+ high: Flag,
+}
+
+impl Dropped {
+ fn none(&self) -> bool {
+ !self.low.get() && !self.mid.get() && !self.high.get()
+ }
+
+ fn all(&self) -> bool {
+ self.low.get() && self.mid.get() && self.high.get()
+ }
+}
+
+fn make_chain() -> (Error, Dropped) {
+ let dropped = Dropped {
+ low: Flag::new(),
+ mid: Flag::new(),
+ high: Flag::new(),
+ };
+
+ let low = LowLevel {
+ message: "no such file or directory",
+ drop: DetectDrop::new(&dropped.low),
+ };
+
+ // impl Context for Result<T, E>
+ let mid = Err::<(), LowLevel>(low)
+ .context(MidLevel {
+ message: "failed to load config",
+ drop: DetectDrop::new(&dropped.mid),
+ })
+ .unwrap_err();
+
+ // impl Context for Result<T, Error>
+ let high = Err::<(), Error>(mid)
+ .context(HighLevel {
+ message: "failed to start server",
+ drop: DetectDrop::new(&dropped.high),
+ })
+ .unwrap_err();
+
+ (high, dropped)
+}
+
+#[test]
+fn test_downcast_ref() {
+ let (err, dropped) = make_chain();
+
+ assert!(!err.is::<String>());
+ assert!(err.downcast_ref::<String>().is_none());
+
+ assert!(err.is::<HighLevel>());
+ let high = err.downcast_ref::<HighLevel>().unwrap();
+ assert_eq!(high.to_string(), "failed to start server");
+
+ assert!(err.is::<MidLevel>());
+ let mid = err.downcast_ref::<MidLevel>().unwrap();
+ assert_eq!(mid.to_string(), "failed to load config");
+
+ assert!(err.is::<LowLevel>());
+ let low = err.downcast_ref::<LowLevel>().unwrap();
+ assert_eq!(low.to_string(), "no such file or directory");
+
+ assert!(dropped.none());
+ drop(err);
+ assert!(dropped.all());
+}
+
+#[test]
+fn test_downcast_high() {
+ let (err, dropped) = make_chain();
+
+ let err = err.downcast::<HighLevel>().unwrap();
+ assert!(!dropped.high.get());
+ assert!(dropped.low.get() && dropped.mid.get());
+
+ drop(err);
+ assert!(dropped.all());
+}
+
+#[test]
+fn test_downcast_mid() {
+ let (err, dropped) = make_chain();
+
+ let err = err.downcast::<MidLevel>().unwrap();
+ assert!(!dropped.mid.get());
+ assert!(dropped.low.get() && dropped.high.get());
+
+ drop(err);
+ assert!(dropped.all());
+}
+
+#[test]
+fn test_downcast_low() {
+ let (err, dropped) = make_chain();
+
+ let err = err.downcast::<LowLevel>().unwrap();
+ assert!(!dropped.low.get());
+ assert!(dropped.mid.get() && dropped.high.get());
+
+ drop(err);
+ assert!(dropped.all());
+}
+
+#[test]
+fn test_unsuccessful_downcast() {
+ let (err, dropped) = make_chain();
+
+ let err = err.downcast::<String>().unwrap_err();
+ assert!(dropped.none());
+
+ drop(err);
+ assert!(dropped.all());
+}
diff --git a/third_party/rust/anyhow/tests/test_convert.rs b/third_party/rust/anyhow/tests/test_convert.rs
new file mode 100644
index 0000000000..72da020be6
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_convert.rs
@@ -0,0 +1,24 @@
+mod drop;
+
+use self::drop::{DetectDrop, Flag};
+use anyhow::{Error, Result};
+use std::error::Error as StdError;
+
+#[test]
+fn test_convert() {
+ let has_dropped = Flag::new();
+ let error = Error::new(DetectDrop::new(&has_dropped));
+ let box_dyn = Box::<dyn StdError + Send + Sync>::from(error);
+ assert_eq!("oh no!", box_dyn.to_string());
+ drop(box_dyn);
+ assert!(has_dropped.get());
+}
+
+#[test]
+fn test_question_mark() -> Result<(), Box<dyn StdError>> {
+ fn f() -> Result<()> {
+ Ok(())
+ }
+ f()?;
+ Ok(())
+}
diff --git a/third_party/rust/anyhow/tests/test_downcast.rs b/third_party/rust/anyhow/tests/test_downcast.rs
new file mode 100644
index 0000000000..c2c3e129ff
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_downcast.rs
@@ -0,0 +1,106 @@
+mod common;
+mod drop;
+
+use self::common::*;
+use self::drop::{DetectDrop, Flag};
+use anyhow::Error;
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+
+#[test]
+fn test_downcast() {
+ assert_eq!(
+ "oh no!",
+ bail_literal().unwrap_err().downcast::<&str>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_fmt().unwrap_err().downcast::<String>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_error()
+ .unwrap_err()
+ .downcast::<io::Error>()
+ .unwrap()
+ .to_string(),
+ );
+}
+
+#[test]
+fn test_downcast_ref() {
+ assert_eq!(
+ "oh no!",
+ *bail_literal().unwrap_err().downcast_ref::<&str>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_fmt().unwrap_err().downcast_ref::<String>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_error()
+ .unwrap_err()
+ .downcast_ref::<io::Error>()
+ .unwrap()
+ .to_string(),
+ );
+}
+
+#[test]
+fn test_downcast_mut() {
+ assert_eq!(
+ "oh no!",
+ *bail_literal().unwrap_err().downcast_mut::<&str>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_fmt().unwrap_err().downcast_mut::<String>().unwrap(),
+ );
+ assert_eq!(
+ "oh no!",
+ bail_error()
+ .unwrap_err()
+ .downcast_mut::<io::Error>()
+ .unwrap()
+ .to_string(),
+ );
+}
+
+#[test]
+fn test_drop() {
+ let has_dropped = Flag::new();
+ let error = Error::new(DetectDrop::new(&has_dropped));
+ drop(error.downcast::<DetectDrop>().unwrap());
+ assert!(has_dropped.get());
+}
+
+#[test]
+fn test_large_alignment() {
+ #[repr(align(64))]
+ #[derive(Debug)]
+ struct LargeAlignedError(&'static str);
+
+ impl Display for LargeAlignedError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(self.0)
+ }
+ }
+
+ impl StdError for LargeAlignedError {}
+
+ let error = Error::new(LargeAlignedError("oh no!"));
+ assert_eq!(
+ "oh no!",
+ error.downcast_ref::<LargeAlignedError>().unwrap().0
+ );
+}
+
+#[test]
+fn test_unsuccessful_downcast() {
+ let mut error = bail_error().unwrap_err();
+ assert!(error.downcast_ref::<&str>().is_none());
+ assert!(error.downcast_mut::<&str>().is_none());
+ assert!(error.downcast::<&str>().is_err());
+}
diff --git a/third_party/rust/anyhow/tests/test_fmt.rs b/third_party/rust/anyhow/tests/test_fmt.rs
new file mode 100644
index 0000000000..cc4929197d
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_fmt.rs
@@ -0,0 +1,94 @@
+use anyhow::{bail, Context, Result};
+use std::io;
+
+fn f() -> Result<()> {
+ bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!"));
+}
+
+fn g() -> Result<()> {
+ f().context("f failed")
+}
+
+fn h() -> Result<()> {
+ g().context("g failed")
+}
+
+const EXPECTED_ALTDISPLAY_F: &str = "oh no!";
+
+const EXPECTED_ALTDISPLAY_G: &str = "f failed: oh no!";
+
+const EXPECTED_ALTDISPLAY_H: &str = "g failed: f failed: oh no!";
+
+const EXPECTED_DEBUG_F: &str = "oh no!";
+
+const EXPECTED_DEBUG_G: &str = "\
+f failed
+
+Caused by:
+ oh no!\
+";
+
+const EXPECTED_DEBUG_H: &str = "\
+g failed
+
+Caused by:
+ 0: f failed
+ 1: oh no!\
+";
+
+const EXPECTED_ALTDEBUG_F: &str = "\
+Custom {
+ kind: PermissionDenied,
+ error: \"oh no!\",
+}\
+";
+
+const EXPECTED_ALTDEBUG_G: &str = "\
+Error {
+ context: \"f failed\",
+ source: Custom {
+ kind: PermissionDenied,
+ error: \"oh no!\",
+ },
+}\
+";
+
+const EXPECTED_ALTDEBUG_H: &str = "\
+Error {
+ context: \"g failed\",
+ source: Error {
+ context: \"f failed\",
+ source: Custom {
+ kind: PermissionDenied,
+ error: \"oh no!\",
+ },
+ },
+}\
+";
+
+#[test]
+fn test_display() {
+ assert_eq!("g failed", h().unwrap_err().to_string());
+}
+
+#[test]
+fn test_altdisplay() {
+ assert_eq!(EXPECTED_ALTDISPLAY_F, format!("{:#}", f().unwrap_err()));
+ assert_eq!(EXPECTED_ALTDISPLAY_G, format!("{:#}", g().unwrap_err()));
+ assert_eq!(EXPECTED_ALTDISPLAY_H, format!("{:#}", h().unwrap_err()));
+}
+
+#[test]
+#[cfg_attr(not(backtrace), ignore)]
+fn test_debug() {
+ assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err()));
+ assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err()));
+ assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err()));
+}
+
+#[test]
+fn test_altdebug() {
+ assert_eq!(EXPECTED_ALTDEBUG_F, format!("{:#?}", f().unwrap_err()));
+ assert_eq!(EXPECTED_ALTDEBUG_G, format!("{:#?}", g().unwrap_err()));
+ assert_eq!(EXPECTED_ALTDEBUG_H, format!("{:#?}", h().unwrap_err()));
+}
diff --git a/third_party/rust/anyhow/tests/test_macros.rs b/third_party/rust/anyhow/tests/test_macros.rs
new file mode 100644
index 0000000000..c6888b6b63
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_macros.rs
@@ -0,0 +1,33 @@
+mod common;
+
+use self::common::*;
+use anyhow::ensure;
+
+#[test]
+fn test_messages() {
+ assert_eq!("oh no!", bail_literal().unwrap_err().to_string());
+ assert_eq!("oh no!", bail_fmt().unwrap_err().to_string());
+ assert_eq!("oh no!", bail_error().unwrap_err().to_string());
+}
+
+#[test]
+fn test_ensure() {
+ let f = || {
+ ensure!(1 + 1 == 2, "This is correct");
+ Ok(())
+ };
+ assert!(f().is_ok());
+
+ let v = 1;
+ let f = || {
+ ensure!(v + v == 2, "This is correct, v: {}", v);
+ Ok(())
+ };
+ assert!(f().is_ok());
+
+ let f = || {
+ ensure!(v + v == 1, "This is not correct, v: {}", v);
+ Ok(())
+ };
+ assert!(f().is_err());
+}
diff --git a/third_party/rust/anyhow/tests/test_repr.rs b/third_party/rust/anyhow/tests/test_repr.rs
new file mode 100644
index 0000000000..72f5002ae1
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_repr.rs
@@ -0,0 +1,29 @@
+mod drop;
+
+use self::drop::{DetectDrop, Flag};
+use anyhow::Error;
+use std::marker::Unpin;
+use std::mem;
+
+#[test]
+fn test_error_size() {
+ assert_eq!(mem::size_of::<Error>(), mem::size_of::<usize>());
+}
+
+#[test]
+fn test_null_pointer_optimization() {
+ assert_eq!(mem::size_of::<Result<(), Error>>(), mem::size_of::<usize>());
+}
+
+#[test]
+fn test_autotraits() {
+ fn assert<E: Unpin + Send + Sync + 'static>() {}
+ assert::<Error>();
+}
+
+#[test]
+fn test_drop() {
+ let has_dropped = Flag::new();
+ drop(Error::new(DetectDrop::new(&has_dropped)));
+ assert!(has_dropped.get());
+}
diff --git a/third_party/rust/anyhow/tests/test_source.rs b/third_party/rust/anyhow/tests/test_source.rs
new file mode 100644
index 0000000000..018267d315
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_source.rs
@@ -0,0 +1,62 @@
+use anyhow::anyhow;
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+
+#[derive(Debug)]
+enum TestError {
+ Io(io::Error),
+}
+
+impl Display for TestError {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ TestError::Io(e) => Display::fmt(e, formatter),
+ }
+ }
+}
+
+impl StdError for TestError {
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ match self {
+ TestError::Io(io) => Some(io),
+ }
+ }
+}
+
+#[test]
+fn test_literal_source() {
+ let error = anyhow!("oh no!");
+ assert!(error.source().is_none());
+}
+
+#[test]
+fn test_variable_source() {
+ let msg = "oh no!";
+ let error = anyhow!(msg);
+ assert!(error.source().is_none());
+
+ let msg = msg.to_owned();
+ let error = anyhow!(msg);
+ assert!(error.source().is_none());
+}
+
+#[test]
+fn test_fmt_source() {
+ let error = anyhow!("{} {}!", "oh", "no");
+ assert!(error.source().is_none());
+}
+
+#[test]
+fn test_io_source() {
+ let io = io::Error::new(io::ErrorKind::Other, "oh no!");
+ let error = anyhow!(TestError::Io(io));
+ assert_eq!("oh no!", error.source().unwrap().to_string());
+}
+
+#[test]
+fn test_anyhow_from_anyhow() {
+ let error = anyhow!("oh no!").context("context");
+ let error = anyhow!(error);
+ assert_eq!("oh no!", error.source().unwrap().to_string());
+}
diff --git a/third_party/rust/anyhow/tests/ui/no-impl.rs b/third_party/rust/anyhow/tests/ui/no-impl.rs
new file mode 100644
index 0000000000..d2e89afc1b
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/no-impl.rs
@@ -0,0 +1,8 @@
+use anyhow::anyhow;
+
+#[derive(Debug)]
+struct Error;
+
+fn main() {
+ let _ = anyhow!(Error);
+}
diff --git a/third_party/rust/anyhow/tests/ui/no-impl.stderr b/third_party/rust/anyhow/tests/ui/no-impl.stderr
new file mode 100644
index 0000000000..be957370d3
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/no-impl.stderr
@@ -0,0 +1,21 @@
+error[E0599]: no method named `anyhow_kind` found for reference `&Error` in the current scope
+ --> $DIR/no-impl.rs:7:13
+ |
+4 | struct Error;
+ | -------------
+ | |
+ | doesn't satisfy `Error: anyhow::kind::TraitKind`
+ | doesn't satisfy `Error: std::convert::Into<anyhow::Error>`
+ | doesn't satisfy `Error: std::fmt::Display`
+...
+7 | let _ = anyhow!(Error);
+ | ^^^^^^^^^^^^^^ method not found in `&Error`
+ |
+ = note: the method `anyhow_kind` exists but the following trait bounds were not satisfied:
+ `Error: std::convert::Into<anyhow::Error>`
+ which is required by `Error: anyhow::kind::TraitKind`
+ `Error: std::fmt::Display`
+ which is required by `&Error: anyhow::kind::AdhocKind`
+ `&Error: std::convert::Into<anyhow::Error>`
+ which is required by `&Error: anyhow::kind::TraitKind`
+ = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)