summaryrefslogtreecommitdiffstats
path: root/third_party/rust/anyhow
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
commit9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/rust/anyhow
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
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.toml66
-rw-r--r--third_party/rust/anyhow/LICENSE-APACHE176
-rw-r--r--third_party/rust/anyhow/LICENSE-MIT23
-rw-r--r--third_party/rust/anyhow/README.md182
-rw-r--r--third_party/rust/anyhow/build.rs131
-rw-r--r--third_party/rust/anyhow/rust-toolchain.toml2
-rw-r--r--third_party/rust/anyhow/src/backtrace.rs401
-rw-r--r--third_party/rust/anyhow/src/chain.rs102
-rw-r--r--third_party/rust/anyhow/src/context.rs193
-rw-r--r--third_party/rust/anyhow/src/ensure.rs834
-rw-r--r--third_party/rust/anyhow/src/error.rs992
-rw-r--r--third_party/rust/anyhow/src/fmt.rs155
-rw-r--r--third_party/rust/anyhow/src/kind.rs116
-rw-r--r--third_party/rust/anyhow/src/lib.rs680
-rw-r--r--third_party/rust/anyhow/src/macros.rs231
-rw-r--r--third_party/rust/anyhow/src/ptr.rs199
-rw-r--r--third_party/rust/anyhow/src/wrapper.rs81
-rw-r--r--third_party/rust/anyhow/tests/common/mod.rs14
-rw-r--r--third_party/rust/anyhow/tests/compiletest.rs7
-rw-r--r--third_party/rust/anyhow/tests/drop/mod.rs53
-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.rs45
-rw-r--r--third_party/rust/anyhow/tests/test_chain.rs69
-rw-r--r--third_party/rust/anyhow/tests/test_context.rs172
-rw-r--r--third_party/rust/anyhow/tests/test_convert.rs46
-rw-r--r--third_party/rust/anyhow/tests/test_downcast.rs123
-rw-r--r--third_party/rust/anyhow/tests/test_ensure.rs718
-rw-r--r--third_party/rust/anyhow/tests/test_ffi.rs18
-rw-r--r--third_party/rust/anyhow/tests/test_fmt.rs94
-rw-r--r--third_party/rust/anyhow/tests/test_macros.rs80
-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/chained-comparison.rs8
-rw-r--r--third_party/rust/anyhow/tests/ui/chained-comparison.stderr10
-rw-r--r--third_party/rust/anyhow/tests/ui/empty-ensure.rs6
-rw-r--r--third_party/rust/anyhow/tests/ui/empty-ensure.stderr12
-rw-r--r--third_party/rust/anyhow/tests/ui/must-use.rs11
-rw-r--r--third_party/rust/anyhow/tests/ui/must-use.stderr12
-rw-r--r--third_party/rust/anyhow/tests/ui/no-impl.rs8
-rw-r--r--third_party/rust/anyhow/tests/ui/no-impl.stderr31
-rw-r--r--third_party/rust/anyhow/tests/ui/temporary-value.rs5
-rw-r--r--third_party/rust/anyhow/tests/ui/temporary-value.stderr9
-rw-r--r--third_party/rust/anyhow/tests/ui/wrong-interpolation.rs5
-rw-r--r--third_party/rust/anyhow/tests/ui/wrong-interpolation.stderr5
46 files changed, 6243 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..2062dae230
--- /dev/null
+++ b/third_party/rust/anyhow/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"5fdf632cfab3b69bc900d04bd0db9ba771e73b36bc56515f2c13332b7f132091","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"62fc2a591c37e781f76fe4d89bcd964eca4fbde246bc43cd4e2fe9db2d30ee70","build.rs":"88bf7100143c79c0af683da7f28deaac031c9b9b213a6426560dc089b0ba45aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"5b4103a7d24d6f438a64b8cc0fafe28d55fc0ca090368174ce44d64e3940badd","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"e129c580b5c2f3017dd977e4122a93f9fbc04b451e930d68f390f51e6be3bdcb","src/ensure.rs":"498bc9c7fb8b93168ed12f532cb97df6ccdda9ce25371586d7f5b1b1c98a14bf","src/error.rs":"e45d4dcfe64b1823b42fbf9bb260e6437987e8c2d51f92434db9d808b36e700a","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"332854c5eb07d44447c356a2e7dc585634b0da1ffbbfa81269c369deaefbc247","src/lib.rs":"cc000cada9b90ce0b9b9aaaeb56055b583dd055f48bd1444206dcc8a9b8a9935","src/macros.rs":"dd35f2ec2a0a25e4504fb04bcd42f6d0963bc0035aaaefc412f5ee1d78945fe1","src/ptr.rs":"f4e28bc9feba1e84160ca9d185008a51b5d72e168e6546f3e942f4258c361e19","src/wrapper.rs":"ff3ad72065a30cc32e9acb0614a30703c49c57b941a335c348b6439af684316b","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"3a8a8d7569913bd98c0e27c69d0bda35101e7fde7c056ed57cdd8ed018e4cbcb","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"c68ea8e3db9e887ce3a7314676e7ff5080aac0a37bc12cae9c6652dead93bcfa","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"11f05010bc9b16319884c1286444100e30cddc2ecd1ffe5e0fd3fee5ffb32683","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"315782f5f4246290fe190e3767b22c3dcaffaabc19c5ace0373537d53e765278","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"c2848c5f254b4c061eea6714d9baf709924aba06619eaf2a8b3aee1266b75f9e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"04415aeaa14995f47f06f35fb1f6971d332d2110aabca920c30ab0803d6a0a5e","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"171f6c1c962503855480696e5d39e68946ec2a027b61a6f36ca1ad1b40265c5d","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"} \ 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..d42c4704c0
--- /dev/null
+++ b/third_party/rust/anyhow/Cargo.toml
@@ -0,0 +1,66 @@
+# 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 are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.39"
+name = "anyhow"
+version = "1.0.69"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "Flexible concrete Error type built on std::error::Error"
+documentation = "https://docs.rs/anyhow"
+readme = "README.md"
+keywords = [
+ "error",
+ "error-handling",
+]
+categories = [
+ "rust-patterns",
+ "no-std",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/anyhow"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+rustdoc-args = [
+ "--cfg",
+ "doc_cfg",
+]
+
+[lib]
+doc-scrape-examples = false
+
+[dependencies.backtrace]
+version = "0.3.51"
+optional = true
+
+[dev-dependencies.futures]
+version = "0.3"
+default-features = false
+
+[dev-dependencies.rustversion]
+version = "1.0.6"
+
+[dev-dependencies.syn]
+version = "1.0"
+features = ["full"]
+
+[dev-dependencies.thiserror]
+version = "1.0"
+
+[dev-dependencies.trybuild]
+version = "1.0.66"
+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..1b5ec8b78e
--- /dev/null
+++ b/third_party/rust/anyhow/LICENSE-APACHE
@@ -0,0 +1,176 @@
+ 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
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..6380c1c04c
--- /dev/null
+++ b/third_party/rust/anyhow/README.md
@@ -0,0 +1,182 @@
+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&logo=docs.rs" height="20">](https://docs.rs/anyhow)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/anyhow/ci.yml?branch=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.39+*
+
+<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, or stable with `features = ["backtrace"]`, 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));
+ ```
+
+ A `bail!` macro is provided as a shorthand for the same early return.
+
+ ```rust
+ bail!("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..38006832e2
--- /dev/null
+++ b/third_party/rust/anyhow/build.rs
@@ -0,0 +1,131 @@
+#![allow(clippy::option_if_let_else)]
+
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::{Command, ExitStatus, Stdio};
+use std::str;
+
+#[cfg(all(feature = "backtrace", not(feature = "std")))]
+compile_error! {
+ "`backtrace` feature without `std` feature is not supported"
+}
+
+// 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(error_generic_member_access, provide_any)]
+
+ use std::any::{Demand, Provider};
+ use std::backtrace::{Backtrace, BacktraceStatus};
+ use std::error::Error;
+ use std::fmt::{self, Display};
+
+ #[derive(Debug)]
+ struct E {
+ backtrace: Backtrace,
+ }
+
+ impl Display for E {
+ fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
+ unimplemented!()
+ }
+ }
+
+ impl Error for E {
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ demand.provide_ref(&self.backtrace);
+ }
+ }
+
+ struct P;
+
+ impl Provider for P {
+ fn provide<'a>(&'a self, _demand: &mut Demand<'a>) {}
+ }
+
+ const _: fn() = || {
+ let backtrace: Backtrace = Backtrace::capture();
+ let status: BacktraceStatus = backtrace.status();
+ match status {
+ BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {}
+ }
+ };
+
+ const _: fn(&dyn Error) -> Option<&Backtrace> = |err| err.request_ref::<Backtrace>();
+"#;
+
+fn main() {
+ if cfg!(feature = "std") {
+ match compile_probe() {
+ Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"),
+ _ => {}
+ }
+ }
+
+ let rustc = match rustc_minor_version() {
+ Some(rustc) => rustc,
+ None => return,
+ };
+
+ if rustc < 51 {
+ println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of");
+ }
+
+ if rustc < 52 {
+ println!("cargo:rustc-cfg=anyhow_no_fmt_arguments_as_str");
+ }
+}
+
+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()?;
+
+ // Make sure to pick up Cargo rustc configuration.
+ let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
+ let mut cmd = Command::new(wrapper);
+ // The wrapper's first argument is supposed to be the path to rustc.
+ cmd.arg(rustc);
+ cmd
+ } else {
+ Command::new(rustc)
+ };
+
+ cmd.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);
+
+ if let Some(target) = env::var_os("TARGET") {
+ cmd.arg("--target").arg(target);
+ }
+
+ // If Cargo wants to set RUSTFLAGS, use that.
+ if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") {
+ if !rustflags.is_empty() {
+ for arg in rustflags.split('\x1f') {
+ cmd.arg(arg);
+ }
+ }
+ }
+
+ cmd.status().ok()
+}
+
+fn rustc_minor_version() -> Option<u32> {
+ let rustc = env::var_os("RUSTC")?;
+ let output = Command::new(rustc).arg("--version").output().ok()?;
+ let version = str::from_utf8(&output.stdout).ok()?;
+ let mut pieces = version.split('.');
+ if pieces.next() != Some("rustc 1") {
+ return None;
+ }
+ pieces.next()?.parse().ok()
+}
diff --git a/third_party/rust/anyhow/rust-toolchain.toml b/third_party/rust/anyhow/rust-toolchain.toml
new file mode 100644
index 0000000000..20fe888c30
--- /dev/null
+++ b/third_party/rust/anyhow/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+components = ["rust-src"]
diff --git a/third_party/rust/anyhow/src/backtrace.rs b/third_party/rust/anyhow/src/backtrace.rs
new file mode 100644
index 0000000000..23c0c85ce2
--- /dev/null
+++ b/third_party/rust/anyhow/src/backtrace.rs
@@ -0,0 +1,401 @@
+#[cfg(backtrace)]
+pub(crate) use std::backtrace::{Backtrace, BacktraceStatus};
+
+#[cfg(all(not(backtrace), feature = "backtrace"))]
+pub(crate) use self::capture::{Backtrace, BacktraceStatus};
+
+#[cfg(not(any(backtrace, feature = "backtrace")))]
+pub(crate) enum Backtrace {}
+
+#[cfg(backtrace)]
+macro_rules! impl_backtrace {
+ () => {
+ std::backtrace::Backtrace
+ };
+}
+
+#[cfg(all(not(backtrace), feature = "backtrace"))]
+macro_rules! impl_backtrace {
+ () => {
+ impl core::fmt::Debug + core::fmt::Display
+ };
+}
+
+#[cfg(any(backtrace, feature = "backtrace"))]
+macro_rules! backtrace {
+ () => {
+ Some(crate::backtrace::Backtrace::capture())
+ };
+}
+
+#[cfg(not(any(backtrace, feature = "backtrace")))]
+macro_rules! backtrace {
+ () => {
+ None
+ };
+}
+
+#[cfg(backtrace)]
+macro_rules! backtrace_if_absent {
+ ($err:expr) => {
+ match ($err as &dyn std::error::Error).request_ref::<std::backtrace::Backtrace>() {
+ Some(_) => None,
+ None => backtrace!(),
+ }
+ };
+}
+
+#[cfg(all(feature = "std", not(backtrace), feature = "backtrace"))]
+macro_rules! backtrace_if_absent {
+ ($err:expr) => {
+ backtrace!()
+ };
+}
+
+#[cfg(all(feature = "std", not(backtrace), not(feature = "backtrace")))]
+macro_rules! backtrace_if_absent {
+ ($err:expr) => {
+ None
+ };
+}
+
+#[cfg(all(not(backtrace), feature = "backtrace"))]
+mod capture {
+ use backtrace::{BacktraceFmt, BytesOrWideString, Frame, PrintFmt, SymbolName};
+ use core::cell::UnsafeCell;
+ use core::fmt::{self, Debug, Display};
+ use core::sync::atomic::{AtomicUsize, Ordering};
+ use std::borrow::Cow;
+ use std::env;
+ use std::path::{self, Path, PathBuf};
+ use std::sync::Once;
+
+ pub(crate) struct Backtrace {
+ inner: Inner,
+ }
+
+ pub(crate) enum BacktraceStatus {
+ Unsupported,
+ Disabled,
+ Captured,
+ }
+
+ enum Inner {
+ Unsupported,
+ Disabled,
+ Captured(LazilyResolvedCapture),
+ }
+
+ struct Capture {
+ actual_start: usize,
+ resolved: bool,
+ frames: Vec<BacktraceFrame>,
+ }
+
+ struct BacktraceFrame {
+ frame: Frame,
+ symbols: Vec<BacktraceSymbol>,
+ }
+
+ struct BacktraceSymbol {
+ name: Option<Vec<u8>>,
+ filename: Option<BytesOrWide>,
+ lineno: Option<u32>,
+ colno: Option<u32>,
+ }
+
+ enum BytesOrWide {
+ Bytes(Vec<u8>),
+ Wide(Vec<u16>),
+ }
+
+ impl Debug for Backtrace {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let capture = match &self.inner {
+ Inner::Unsupported => return fmt.write_str("<unsupported>"),
+ Inner::Disabled => return fmt.write_str("<disabled>"),
+ Inner::Captured(c) => c.force(),
+ };
+
+ let frames = &capture.frames[capture.actual_start..];
+
+ write!(fmt, "Backtrace ")?;
+
+ let mut dbg = fmt.debug_list();
+
+ for frame in frames {
+ if frame.frame.ip().is_null() {
+ continue;
+ }
+
+ dbg.entries(&frame.symbols);
+ }
+
+ dbg.finish()
+ }
+ }
+
+ impl Debug for BacktraceFrame {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let mut dbg = fmt.debug_list();
+ dbg.entries(&self.symbols);
+ dbg.finish()
+ }
+ }
+
+ impl Debug for BacktraceSymbol {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "{{ ")?;
+
+ if let Some(fn_name) = self.name.as_ref().map(|b| SymbolName::new(b)) {
+ write!(fmt, "fn: \"{:#}\"", fn_name)?;
+ } else {
+ write!(fmt, "fn: <unknown>")?;
+ }
+
+ if let Some(fname) = self.filename.as_ref() {
+ write!(fmt, ", file: \"{:?}\"", fname)?;
+ }
+
+ if let Some(line) = self.lineno {
+ write!(fmt, ", line: {:?}", line)?;
+ }
+
+ write!(fmt, " }}")
+ }
+ }
+
+ impl Debug for BytesOrWide {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ output_filename(
+ fmt,
+ match self {
+ BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
+ BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
+ },
+ PrintFmt::Short,
+ env::current_dir().as_ref().ok(),
+ )
+ }
+ }
+
+ impl Backtrace {
+ fn enabled() -> bool {
+ static ENABLED: AtomicUsize = AtomicUsize::new(0);
+ match ENABLED.load(Ordering::Relaxed) {
+ 0 => {}
+ 1 => return false,
+ _ => return true,
+ }
+ let enabled = match env::var_os("RUST_LIB_BACKTRACE") {
+ Some(s) => s != "0",
+ None => match env::var_os("RUST_BACKTRACE") {
+ Some(s) => s != "0",
+ None => false,
+ },
+ };
+ ENABLED.store(enabled as usize + 1, Ordering::Relaxed);
+ enabled
+ }
+
+ #[inline(never)] // want to make sure there's a frame here to remove
+ pub(crate) fn capture() -> Backtrace {
+ if Backtrace::enabled() {
+ Backtrace::create(Backtrace::capture as usize)
+ } else {
+ let inner = Inner::Disabled;
+ Backtrace { inner }
+ }
+ }
+
+ // Capture a backtrace which starts just before the function addressed
+ // by `ip`
+ fn create(ip: usize) -> Backtrace {
+ let mut frames = Vec::new();
+ let mut actual_start = None;
+ backtrace::trace(|frame| {
+ frames.push(BacktraceFrame {
+ frame: frame.clone(),
+ symbols: Vec::new(),
+ });
+ if frame.symbol_address() as usize == ip && actual_start.is_none() {
+ actual_start = Some(frames.len() + 1);
+ }
+ true
+ });
+
+ // If no frames came out assume that this is an unsupported platform
+ // since `backtrace` doesn't provide a way of learning this right
+ // now, and this should be a good enough approximation.
+ let inner = if frames.is_empty() {
+ Inner::Unsupported
+ } else {
+ Inner::Captured(LazilyResolvedCapture::new(Capture {
+ actual_start: actual_start.unwrap_or(0),
+ frames,
+ resolved: false,
+ }))
+ };
+
+ Backtrace { inner }
+ }
+
+ pub(crate) fn status(&self) -> BacktraceStatus {
+ match self.inner {
+ Inner::Unsupported => BacktraceStatus::Unsupported,
+ Inner::Disabled => BacktraceStatus::Disabled,
+ Inner::Captured(_) => BacktraceStatus::Captured,
+ }
+ }
+ }
+
+ impl Display for Backtrace {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let capture = match &self.inner {
+ Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
+ Inner::Disabled => return fmt.write_str("disabled backtrace"),
+ Inner::Captured(c) => c.force(),
+ };
+
+ let full = fmt.alternate();
+ let (frames, style) = if full {
+ (&capture.frames[..], PrintFmt::Full)
+ } else {
+ (&capture.frames[capture.actual_start..], PrintFmt::Short)
+ };
+
+ // When printing paths we try to strip the cwd if it exists,
+ // otherwise we just print the path as-is. Note that we also only do
+ // this for the short format, because if it's full we presumably
+ // want to print everything.
+ let cwd = env::current_dir();
+ let mut print_path = move |fmt: &mut fmt::Formatter, path: BytesOrWideString| {
+ output_filename(fmt, path, style, cwd.as_ref().ok())
+ };
+
+ let mut f = BacktraceFmt::new(fmt, style, &mut print_path);
+ f.add_context()?;
+ for frame in frames {
+ let mut f = f.frame();
+ if frame.symbols.is_empty() {
+ f.print_raw(frame.frame.ip(), None, None, None)?;
+ } else {
+ for symbol in frame.symbols.iter() {
+ f.print_raw_with_column(
+ frame.frame.ip(),
+ symbol.name.as_ref().map(|b| SymbolName::new(b)),
+ symbol.filename.as_ref().map(|b| match b {
+ BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
+ BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
+ }),
+ symbol.lineno,
+ symbol.colno,
+ )?;
+ }
+ }
+ }
+ f.finish()?;
+ Ok(())
+ }
+ }
+
+ struct LazilyResolvedCapture {
+ sync: Once,
+ capture: UnsafeCell<Capture>,
+ }
+
+ impl LazilyResolvedCapture {
+ fn new(capture: Capture) -> Self {
+ LazilyResolvedCapture {
+ sync: Once::new(),
+ capture: UnsafeCell::new(capture),
+ }
+ }
+
+ fn force(&self) -> &Capture {
+ self.sync.call_once(|| {
+ // Safety: This exclusive reference can't overlap with any
+ // others. `Once` guarantees callers will block until this
+ // closure returns. `Once` also guarantees only a single caller
+ // will enter this closure.
+ unsafe { &mut *self.capture.get() }.resolve();
+ });
+
+ // Safety: This shared reference can't overlap with the exclusive
+ // reference above.
+ unsafe { &*self.capture.get() }
+ }
+ }
+
+ // Safety: Access to the inner value is synchronized using a thread-safe
+ // `Once`. So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
+ unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
+
+ impl Capture {
+ fn resolve(&mut self) {
+ // If we're already resolved, nothing to do!
+ if self.resolved {
+ return;
+ }
+ self.resolved = true;
+
+ for frame in self.frames.iter_mut() {
+ let symbols = &mut frame.symbols;
+ let frame = &frame.frame;
+ backtrace::resolve_frame(frame, |symbol| {
+ symbols.push(BacktraceSymbol {
+ name: symbol.name().map(|m| m.as_bytes().to_vec()),
+ filename: symbol.filename_raw().map(|b| match b {
+ BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()),
+ BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
+ }),
+ lineno: symbol.lineno(),
+ colno: symbol.colno(),
+ });
+ });
+ }
+ }
+ }
+
+ // Prints the filename of the backtrace frame.
+ fn output_filename(
+ fmt: &mut fmt::Formatter,
+ bows: BytesOrWideString,
+ print_fmt: PrintFmt,
+ cwd: Option<&PathBuf>,
+ ) -> fmt::Result {
+ let file: Cow<Path> = match bows {
+ #[cfg(unix)]
+ BytesOrWideString::Bytes(bytes) => {
+ use std::os::unix::ffi::OsStrExt;
+ Path::new(std::ffi::OsStr::from_bytes(bytes)).into()
+ }
+ #[cfg(not(unix))]
+ BytesOrWideString::Bytes(bytes) => {
+ Path::new(std::str::from_utf8(bytes).unwrap_or("<unknown>")).into()
+ }
+ #[cfg(windows)]
+ BytesOrWideString::Wide(wide) => {
+ use std::os::windows::ffi::OsStringExt;
+ Cow::Owned(std::ffi::OsString::from_wide(wide).into())
+ }
+ #[cfg(not(windows))]
+ BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(),
+ };
+ if print_fmt == PrintFmt::Short && file.is_absolute() {
+ if let Some(cwd) = cwd {
+ if let Ok(stripped) = file.strip_prefix(&cwd) {
+ if let Some(s) = stripped.to_str() {
+ return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s);
+ }
+ }
+ }
+ }
+ Display::fmt(&file.display(), fmt)
+ }
+}
+
+fn _assert_send_sync() {
+ fn _assert<T: Send + Sync>() {}
+ _assert::<Backtrace>();
+}
diff --git a/third_party/rust/anyhow/src/chain.rs b/third_party/rust/anyhow/src/chain.rs
new file mode 100644
index 0000000000..f7baff29f1
--- /dev/null
+++ b/third_party/rust/anyhow/src/chain.rs
@@ -0,0 +1,102 @@
+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> {
+ #[cold]
+ 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..9df86937bd
--- /dev/null
+++ b/third_party/rust/anyhow/src/context.rs
@@ -0,0 +1,193 @@
+use crate::error::ContextError;
+use crate::{Context, Error, StdError};
+use core::convert::Infallible;
+use core::fmt::{self, Debug, Display, Write};
+
+#[cfg(backtrace)]
+use std::any::{Demand, Provider};
+
+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,
+ {
+ // Not using map_err to save 2 useless frames off the captured backtrace
+ // in ext_context.
+ match self {
+ Ok(ok) => Ok(ok),
+ Err(error) => Err(error.ext_context(context)),
+ }
+ }
+
+ fn with_context<C, F>(self, context: F) -> Result<T, Error>
+ where
+ C: Display + Send + Sync + 'static,
+ F: FnOnce() -> C,
+ {
+ match self {
+ Ok(ok) => Ok(ok),
+ Err(error) => Err(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,
+ {
+ // Not using ok_or_else to save 2 useless frames off the captured
+ // backtrace.
+ match self {
+ Some(ok) => Ok(ok),
+ None => Err(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,
+ {
+ match self {
+ Some(ok) => Ok(ok),
+ None => Err(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,
+{
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ Some(&self.error)
+ }
+
+ #[cfg(backtrace)]
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ StdError::provide(&self.error, demand);
+ }
+}
+
+impl<C> StdError for ContextError<C, Error>
+where
+ C: Display,
+{
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) })
+ }
+
+ #[cfg(backtrace)]
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ Provider::provide(&self.error, demand);
+ }
+}
+
+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/ensure.rs b/third_party/rust/anyhow/src/ensure.rs
new file mode 100644
index 0000000000..0ab4471231
--- /dev/null
+++ b/third_party/rust/anyhow/src/ensure.rs
@@ -0,0 +1,834 @@
+use crate::Error;
+use alloc::string::String;
+use core::fmt::{self, Debug, Write};
+use core::mem::MaybeUninit;
+use core::ptr;
+use core::slice;
+use core::str;
+
+#[doc(hidden)]
+pub trait BothDebug {
+ fn __dispatch_ensure(self, msg: &'static str) -> Error;
+}
+
+impl<A, B> BothDebug for (A, B)
+where
+ A: Debug,
+ B: Debug,
+{
+ fn __dispatch_ensure(self, msg: &'static str) -> Error {
+ render(msg, &self.0, &self.1)
+ }
+}
+
+#[doc(hidden)]
+pub trait NotBothDebug {
+ fn __dispatch_ensure(self, msg: &'static str) -> Error;
+}
+
+impl<A, B> NotBothDebug for &(A, B) {
+ fn __dispatch_ensure(self, msg: &'static str) -> Error {
+ Error::msg(msg)
+ }
+}
+
+struct Buf {
+ bytes: [MaybeUninit<u8>; 40],
+ written: usize,
+}
+
+impl Buf {
+ fn new() -> Self {
+ Buf {
+ bytes: [MaybeUninit::uninit(); 40],
+ written: 0,
+ }
+ }
+
+ fn as_str(&self) -> &str {
+ unsafe {
+ str::from_utf8_unchecked(slice::from_raw_parts(
+ self.bytes.as_ptr().cast::<u8>(),
+ self.written,
+ ))
+ }
+ }
+}
+
+impl Write for Buf {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ if s.bytes().any(|b| b == b' ' || b == b'\n') {
+ return Err(fmt::Error);
+ }
+
+ let remaining = self.bytes.len() - self.written;
+ if s.len() > remaining {
+ return Err(fmt::Error);
+ }
+
+ unsafe {
+ ptr::copy_nonoverlapping(
+ s.as_ptr(),
+ self.bytes.as_mut_ptr().add(self.written).cast::<u8>(),
+ s.len(),
+ );
+ }
+ self.written += s.len();
+ Ok(())
+ }
+}
+
+fn render(msg: &'static str, lhs: &dyn Debug, rhs: &dyn Debug) -> Error {
+ let mut lhs_buf = Buf::new();
+ if fmt::write(&mut lhs_buf, format_args!("{:?}", lhs)).is_ok() {
+ let mut rhs_buf = Buf::new();
+ if fmt::write(&mut rhs_buf, format_args!("{:?}", rhs)).is_ok() {
+ let lhs_str = lhs_buf.as_str();
+ let rhs_str = rhs_buf.as_str();
+ // "{msg} ({lhs} vs {rhs})"
+ let len = msg.len() + 2 + lhs_str.len() + 4 + rhs_str.len() + 1;
+ let mut string = String::with_capacity(len);
+ string.push_str(msg);
+ string.push_str(" (");
+ string.push_str(lhs_str);
+ string.push_str(" vs ");
+ string.push_str(rhs_str);
+ string.push(')');
+ return Error::msg(string);
+ }
+ }
+ Error::msg(msg)
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __parse_ensure {
+ (atom () $bail:tt $fuel:tt {($($rhs:tt)+) ($($lhs:tt)+) $op:tt} $dup:tt $(,)?) => {
+ $crate::__fancy_ensure!($($lhs)+, $op, $($rhs)+)
+ };
+
+ // low precedence control flow constructs
+
+ (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt return $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+
+ (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt break $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+
+ (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt continue $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+
+ (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt yield $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+
+ (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt move $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+
+ // unary operators
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($deref:tt $($dup:tt)*) * $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $deref) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($not:tt $($dup:tt)*) ! $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $not) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($let:tt $($dup:tt)*) let $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $let) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($life:tt $colon:tt $($dup:tt)*) $label:lifetime : $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $life $colon) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) &mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $mut:tt $($dup:tt)*) &&mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // control flow constructs
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($if:tt $($dup:tt)*) if $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $if) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($match:tt $($dup:tt)*) match $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $match) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($while:tt $($dup:tt)*) while $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $while) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $($dup:tt)*) for $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat (cond $stack) $bail ($($fuel)*) {($($buf)* $for) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom (cond $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(cond $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $if:tt $($dup:tt)*) else if $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $else $if) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $brace:tt $($dup:tt)*) else {$($block:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $else $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (cond $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) $parse $dup $($rest)*)
+ };
+
+ // atomic expressions
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($array:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($loop:tt $block:tt $($dup:tt)*) loop {$($body:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $loop $block) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $block:tt $($dup:tt)*) async {$($body:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $block) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $move:tt $block:tt $($dup:tt)*) async move {$($body:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $move $block) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $block:tt $($dup:tt)*) unsafe {$($body:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $unsafe $block) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // path expressions
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (qpath (epath (atom $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: << $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (< $($rest)*) < $($rest)*)
+ };
+
+ (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: <- $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (- $($rest)*) - $($rest)*)
+ };
+
+ (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(epath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*)
+ };
+
+ // trailer expressions
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($call:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($index:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($init:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($question:tt $($dup:tt)*) ? $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $question) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $langle:tt $($dup:tt)*) . $i:ident :: < $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $($dup:tt)*) . $i:ident :: << $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons <) $($parse)*} (< $($rest)*) < $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $($dup:tt)*) . $i:ident :: <- $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons <) $($parse)*} (- $($rest)*) - $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $($dup:tt)*) . $field:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $field) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $index:tt $($dup:tt)*) . $lit:literal $($rest:tt)*) => {
+ $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $index) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (atom $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // types
+
+ (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $const:tt $($dup:tt)*) *const $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $const) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $mut:tt $($dup:tt)*) *mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $mut:tt $($dup:tt)*) & $l:lifetime mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) & mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $($dup:tt)*) & $l:lifetime $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $mut:tt $($dup:tt)*) && $l:lifetime mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) && mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $($dup:tt)*) && $l:lifetime $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $(extern $($abi:literal)?)? fn $($dup:tt)*) unsafe $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $unsafe) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt $abi:literal fn $($dup:tt)*) extern $lit:literal $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern $abi) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt fn $($dup:tt)*) extern $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $arrow:tt $($dup:tt)*) fn ($($args:tt)*) -> $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $fn $paren $arrow) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $($dup:tt)*) fn ($($args:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $fn $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($impl:tt $($dup:tt)*) impl $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $impl) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dyn:tt $($dup:tt)*) dyn $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $dyn) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($never:tt $($dup:tt)*) ! $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $never) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $langle:tt $($dup:tt)*) for < $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (type $stack) $bail ($($fuel)*) {($($buf)* $for $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // path types
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (qpath (tpath $stack)) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt << $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* <) $($parse)*} (< $($rest)*) < $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt <- $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* <) $($parse)*} (- $($rest)*) - $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: << $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (< $($rest)*) < $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: <- $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (- $($rest)*) - $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $arrow:tt $($dup:tt)*) ($($args:tt)*) -> $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $paren $arrow) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($args:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $arrow:tt $($dup:tt)*) :: ($($args:tt)*) -> $($rest:tt)*) => {
+ $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $colons $paren $arrow) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $($dup:tt)*) :: ($($args:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $colons $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (tpath $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => {
+ $crate::__parse_ensure!(object $stack $bail ($($fuel)*) $parse $dup $($rest)*)
+ };
+
+ // qualified paths
+
+ (qpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $($dup:tt)*) > :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (qpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (qpath $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // trait objects
+
+ (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $colons:tt $($dup:tt)*) + :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $($dup:tt)*) + $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (object ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*)
+ };
+
+ // angle bracketed generic arguments
+
+ (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* >) $($parse)*} (> $($rest)*) > $($rest)*)
+ };
+
+ (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => {
+ $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $life:lifetime $($rest:tt)*) => {
+ $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $life) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assoc:ident $eq:tt $($dup:tt)*) $ident:ident = $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) {($($buf)* $assoc $eq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (generic $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) $parse $dup $($rest)*)
+ };
+
+ (arglist $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($comma:tt $($dup:tt)*) , $($rest:tt)*) => {
+ $crate::__parse_ensure!(generic $stack $bail ($($fuel)*) {($($buf)* $comma) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => {
+ $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* >) $($parse)*} (> $($rest)*) > $($rest)*)
+ };
+
+ // patterns
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($pipe:tt $($dup:tt)*) | $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $pipe) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) = $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($in:tt $($dup:tt)*) in $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $in) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ref:tt $($dup:tt)*) ref $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $ref) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mut:tt $($dup:tt)*) mut $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $mut) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($at:tt $($dup:tt)*) @ $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $at) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) .. $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) ..= $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($content:tt)*} $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => {
+ $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => {
+ $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(type (qpath (epath (pat $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // high precedence binary operators
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($add:tt $($dup:tt)*) + $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $add) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($sub:tt $($dup:tt)*) - $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $sub) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mul:tt $($dup:tt)*) * $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $mul) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($div:tt $($dup:tt)*) / $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $div) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rem:tt $($dup:tt)*) % $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $rem) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxor:tt $($dup:tt)*) ^ $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitxor) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitand:tt $($dup:tt)*) & $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitand) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitor:tt $($dup:tt)*) | $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitor) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shl:tt $($dup:tt)*) << $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shl) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shr:tt $($dup:tt)*) >> $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shr) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // comparison binary operators
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $eq} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $le} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $le) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $lt} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $lt) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ne} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ne) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ge} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ge) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $gt} ($($rest)*) $($rest)*)
+ };
+
+ (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $gt) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // low precedence binary operators
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($or:tt $($dup:tt)*) || $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $or) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assign:tt $($dup:tt)*) = $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $assign) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($addeq:tt $($dup:tt)*) += $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $addeq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($subeq:tt $($dup:tt)*) -= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $subeq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($muleq:tt $($dup:tt)*) *= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $muleq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($diveq:tt $($dup:tt)*) /= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $diveq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($remeq:tt $($dup:tt)*) %= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $remeq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxoreq:tt $($dup:tt)*) ^= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitxoreq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitandeq:tt $($dup:tt)*) &= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitandeq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitoreq:tt $($dup:tt)*) |= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitoreq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shleq:tt $($dup:tt)*) <<= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shleq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shreq:tt $($dup:tt)*) >>= $($rest:tt)*) => {
+ $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shreq) $($parse)*} ($($rest)*) $($rest)*)
+ };
+
+ // unrecognized expression
+
+ ($state:tt $stack:tt ($($bail:tt)*) $($rest:tt)*) => {
+ $crate::__fallback_ensure!($($bail)*)
+ };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __fancy_ensure {
+ ($lhs:expr, $op:tt, $rhs:expr) => {
+ match (&$lhs, &$rhs) {
+ (lhs, rhs) => {
+ if !(lhs $op rhs) {
+ #[allow(unused_imports)]
+ use $crate::__private::{BothDebug, NotBothDebug};
+ return Err((lhs, rhs).__dispatch_ensure(
+ $crate::__private::concat!(
+ "Condition failed: `",
+ $crate::__private::stringify!($lhs),
+ " ",
+ $crate::__private::stringify!($op),
+ " ",
+ $crate::__private::stringify!($rhs),
+ "`",
+ ),
+ ));
+ }
+ }
+ }
+ };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __fallback_ensure {
+ ($cond:expr $(,)?) => {
+ if !$cond {
+ return $crate::__private::Err($crate::Error::msg(
+ $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`")
+ ));
+ }
+ };
+ ($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)*));
+ }
+ };
+}
diff --git a/third_party/rust/anyhow/src/error.rs b/third_party/rust/anyhow/src/error.rs
new file mode 100644
index 0000000000..9f6ce8c10b
--- /dev/null
+++ b/third_party/rust/anyhow/src/error.rs
@@ -0,0 +1,992 @@
+use crate::backtrace::Backtrace;
+use crate::chain::Chain;
+#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))]
+use crate::ptr::Mut;
+use crate::ptr::{Own, Ref};
+use crate::{Error, StdError};
+use alloc::boxed::Box;
+#[cfg(backtrace)]
+use core::any::Demand;
+use core::any::TypeId;
+use core::fmt::{self, Debug, Display};
+use core::mem::ManuallyDrop;
+#[cfg(not(anyhow_no_ptr_addr_of))]
+use core::ptr;
+use core::ptr::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")))]
+ #[cold]
+ #[must_use]
+ 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
+ /// }
+ /// ```
+ #[cold]
+ #[must_use]
+ pub fn msg<M>(message: M) -> Self
+ where
+ M: Display + Debug + Send + Sync + 'static,
+ {
+ Error::from_adhoc(message, backtrace!())
+ }
+
+ #[cfg(feature = "std")]
+ #[cold]
+ 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(anyhow_no_ptr_addr_of)]
+ object_mut: object_mut::<E>,
+ object_boxed: object_boxed::<E>,
+ object_downcast: object_downcast::<E>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: object_downcast_mut::<E>,
+ object_drop_rest: object_drop_front::<E>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: no_backtrace,
+ };
+
+ // Safety: passing vtable that operates on the right type E.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ #[cold]
+ 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(all(feature = "std", anyhow_no_ptr_addr_of))]
+ object_mut: object_mut::<MessageError<M>>,
+ object_boxed: object_boxed::<MessageError<M>>,
+ object_downcast: object_downcast::<M>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: object_downcast_mut::<M>,
+ object_drop_rest: object_drop_front::<M>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: no_backtrace,
+ };
+
+ // 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) }
+ }
+
+ #[cold]
+ 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(all(feature = "std", anyhow_no_ptr_addr_of))]
+ object_mut: object_mut::<DisplayError<M>>,
+ object_boxed: object_boxed::<DisplayError<M>>,
+ object_downcast: object_downcast::<M>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: object_downcast_mut::<M>,
+ object_drop_rest: object_drop_front::<M>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: no_backtrace,
+ };
+
+ // 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")]
+ #[cold]
+ 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(anyhow_no_ptr_addr_of)]
+ object_mut: object_mut::<ContextError<C, E>>,
+ object_boxed: object_boxed::<ContextError<C, E>>,
+ object_downcast: context_downcast::<C, E>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: context_downcast_mut::<C, E>,
+ object_drop_rest: context_drop_rest::<C, E>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: no_backtrace,
+ };
+
+ // Safety: passing vtable that operates on the right type.
+ unsafe { Error::construct(error, vtable, backtrace) }
+ }
+
+ #[cfg(feature = "std")]
+ #[cold]
+ 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(anyhow_no_ptr_addr_of)]
+ object_mut: object_mut::<BoxedError>,
+ object_boxed: object_boxed::<BoxedError>,
+ object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>,
+ object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: no_backtrace,
+ };
+
+ // 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.
+ #[cold]
+ unsafe fn construct<E>(
+ error: E,
+ vtable: &'static ErrorVTable,
+ backtrace: Option<Backtrace>,
+ ) -> Self
+ where
+ E: StdError + Send + Sync + 'static,
+ {
+ let inner: Box<ErrorImpl<E>> = 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 coercion 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 inner = Own::new(inner).cast::<ErrorImpl>();
+ 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)
+ /// })
+ /// }
+ /// ```
+ #[cold]
+ #[must_use]
+ 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(all(feature = "std", anyhow_no_ptr_addr_of))]
+ object_mut: object_mut::<ContextError<C, Error>>,
+ object_boxed: object_boxed::<ContextError<C, Error>>,
+ object_downcast: context_chain_downcast::<C>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: context_chain_downcast_mut::<C>,
+ object_drop_rest: context_chain_drop_rest::<C>,
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: context_backtrace::<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.
+ ///
+ /// 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`.
+ ///
+ /// # Stability
+ ///
+ /// Standard library backtraces are only available on the nightly channel.
+ /// Tracking issue: [rust-lang/rust#53487][tracking].
+ ///
+ /// On stable compilers, this function is only available if the crate's
+ /// "backtrace" feature is enabled, and will use the `backtrace` crate as
+ /// the underlying backtrace implementation.
+ ///
+ /// ```toml
+ /// [dependencies]
+ /// anyhow = { version = "1.0", features = ["backtrace"] }
+ /// ```
+ ///
+ /// [tracking]: https://github.com/rust-lang/rust/issues/53487
+ #[cfg(any(backtrace, feature = "backtrace"))]
+ #[cfg_attr(doc_cfg, doc(cfg(any(nightly, feature = "backtrace"))))]
+ pub fn backtrace(&self) -> &impl_backtrace!() {
+ unsafe { ErrorImpl::backtrace(self.inner.by_ref()) }
+ }
+
+ /// 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")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+ #[cold]
+ pub fn chain(&self) -> Chain {
+ unsafe { ErrorImpl::chain(self.inner.by_ref()) }
+ }
+
+ /// 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")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+ pub fn root_cause(&self) -> &(dyn StdError + 'static) {
+ self.chain().last().unwrap()
+ }
+
+ /// 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>(mut self) -> Result<E, Self>
+ where
+ E: Display + Debug + Send + Sync + 'static,
+ {
+ let target = TypeId::of::<E>();
+ let inner = self.inner.by_mut();
+ unsafe {
+ // Use vtable to find NonNull<()> which points to a value of type E
+ // somewhere inside the data structure.
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) {
+ Some(addr) => addr.by_mut().extend(),
+ None => return Err(self),
+ };
+ #[cfg(anyhow_no_ptr_addr_of)]
+ let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) {
+ Some(addr) => addr.extend(),
+ 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 = addr.cast::<E>().read();
+
+ // Drop rest of the data structure outside of E.
+ (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, 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 = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?;
+ Some(addr.cast::<E>().deref())
+ }
+ }
+
+ /// 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.
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ let addr =
+ (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut();
+
+ #[cfg(anyhow_no_ptr_addr_of)]
+ let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?;
+
+ Some(addr.cast::<E>().deref_mut())
+ }
+ }
+}
+
+#[cfg(backtrace)]
+impl std::any::Provider for Error {
+ // Called by thiserror when you have `#[source] anyhow::Error`. This provide
+ // implementation includes the anyhow::Error's Backtrace if any, unlike
+ // deref'ing to dyn Error where the provide implementation would include
+ // only the original error's Backtrace from before it got wrapped into an
+ // anyhow::Error.
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ unsafe { ErrorImpl::provide(self.inner.by_ref(), demand) }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+impl<E> From<E> for Error
+where
+ E: StdError + Send + Sync + 'static,
+{
+ #[cold]
+ fn from(error: E) -> Self {
+ let backtrace = backtrace_if_absent!(&error);
+ Error::from_std(error, backtrace)
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+impl Deref for Error {
+ type Target = dyn StdError + Send + Sync + 'static;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe { ErrorImpl::error(self.inner.by_ref()) }
+ }
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+impl DerefMut for Error {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe { ErrorImpl::error_mut(self.inner.by_mut()) }
+ }
+}
+
+impl Display for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) }
+ }
+}
+
+impl Debug for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) }
+ }
+}
+
+impl Drop for Error {
+ fn drop(&mut self) {
+ unsafe {
+ // Invoke the vtable's drop behavior.
+ (vtable(self.inner.ptr).object_drop)(self.inner);
+ }
+ }
+}
+
+struct ErrorVTable {
+ object_drop: unsafe fn(Own<ErrorImpl>),
+ object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>,
+ #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
+ object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static),
+ object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>,
+ object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>,
+ #[cfg(anyhow_no_ptr_addr_of)]
+ object_downcast_mut: unsafe fn(Mut<ErrorImpl>, TypeId) -> Option<Mut<()>>,
+ object_drop_rest: unsafe fn(Own<ErrorImpl>, TypeId),
+ #[cfg(all(not(backtrace), feature = "backtrace"))]
+ object_backtrace: unsafe fn(Ref<ErrorImpl>) -> Option<&Backtrace>,
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_drop<E>(e: Own<ErrorImpl>) {
+ // Cast back to ErrorImpl<E> so that the allocator receives the correct
+ // Layout to deallocate the Box's memory.
+ let unerased = e.cast::<ErrorImpl<E>>().boxed();
+ drop(unerased);
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_drop_front<E>(e: Own<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 = e.cast::<ErrorImpl<ManuallyDrop<E>>>().boxed();
+ drop(unerased);
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>
+where
+ E: StdError + Send + Sync + 'static,
+{
+ // Attach E's native StdError vtable onto a pointer to self._object.
+
+ let unerased = e.cast::<ErrorImpl<E>>();
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ return Ref::from_raw(NonNull::new_unchecked(
+ ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
+ ));
+
+ #[cfg(anyhow_no_ptr_addr_of)]
+ return Ref::new(&unerased.deref()._object);
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived
+// from a `&mut`
+#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
+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.cast::<ErrorImpl<E>>().deref_mut()._object
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_boxed<E>(e: Own<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.
+ e.cast::<ErrorImpl<E>>().boxed()
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+unsafe fn object_downcast<E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>>
+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.cast::<ErrorImpl<E>>();
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ return Some(
+ Ref::from_raw(NonNull::new_unchecked(
+ ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
+ ))
+ .cast::<()>(),
+ );
+
+ #[cfg(anyhow_no_ptr_addr_of)]
+ return Some(Ref::new(&unerased.deref()._object).cast::<()>());
+ } else {
+ None
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<E>.
+#[cfg(anyhow_no_ptr_addr_of)]
+unsafe fn object_downcast_mut<E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
+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.cast::<ErrorImpl<E>>().deref_mut();
+ Some(Mut::new(&mut unerased._object).cast::<()>())
+ } else {
+ None
+ }
+}
+
+#[cfg(all(not(backtrace), feature = "backtrace"))]
+fn no_backtrace(e: Ref<ErrorImpl>) -> Option<&Backtrace> {
+ let _ = e;
+ None
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
+#[cfg(feature = "std")]
+unsafe fn context_downcast<C, E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>>
+where
+ C: 'static,
+ E: 'static,
+{
+ if TypeId::of::<C>() == target {
+ let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref();
+ Some(Ref::new(&unerased._object.context).cast::<()>())
+ } else if TypeId::of::<E>() == target {
+ let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref();
+ Some(Ref::new(&unerased._object.error).cast::<()>())
+ } else {
+ None
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
+#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
+unsafe fn context_downcast_mut<C, E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
+where
+ C: 'static,
+ E: 'static,
+{
+ if TypeId::of::<C>() == target {
+ let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref_mut();
+ Some(Mut::new(&mut unerased._object.context).cast::<()>())
+ } else if TypeId::of::<E>() == target {
+ let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref_mut();
+ Some(Mut::new(&mut unerased._object.error).cast::<()>())
+ } else {
+ None
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
+#[cfg(feature = "std")]
+unsafe fn context_drop_rest<C, E>(e: Own<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 = e
+ .cast::<ErrorImpl<ContextError<ManuallyDrop<C>, E>>>()
+ .boxed();
+ drop(unerased);
+ } else {
+ let unerased = e
+ .cast::<ErrorImpl<ContextError<C, ManuallyDrop<E>>>>()
+ .boxed();
+ drop(unerased);
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+unsafe fn context_chain_downcast<C>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>>
+where
+ C: 'static,
+{
+ let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref();
+ if TypeId::of::<C>() == target {
+ Some(Ref::new(&unerased._object.context).cast::<()>())
+ } else {
+ // Recurse down the context chain per the inner error's vtable.
+ let source = &unerased._object.error;
+ (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target)
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+#[cfg(anyhow_no_ptr_addr_of)]
+unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
+where
+ C: 'static,
+{
+ let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref_mut();
+ if TypeId::of::<C>() == target {
+ Some(Mut::new(&mut unerased._object.context).cast::<()>())
+ } else {
+ // Recurse down the context chain per the inner error's vtable.
+ let source = &mut unerased._object.error;
+ (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target)
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+unsafe fn context_chain_drop_rest<C>(e: Own<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 = e
+ .cast::<ErrorImpl<ContextError<ManuallyDrop<C>, Error>>>()
+ .boxed();
+ // Drop the entire rest of the data structure rooted in the next Error.
+ drop(unerased);
+ } else {
+ let unerased = e
+ .cast::<ErrorImpl<ContextError<C, ManuallyDrop<Error>>>>()
+ .boxed();
+ // Read the Own<ErrorImpl> from the next error.
+ let inner = unerased._object.error.inner;
+ drop(unerased);
+ let vtable = vtable(inner.ptr);
+ // Recursively drop the next error using the same target typeid.
+ (vtable.object_drop_rest)(inner, target);
+ }
+}
+
+// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
+#[cfg(all(not(backtrace), feature = "backtrace"))]
+#[allow(clippy::unnecessary_wraps)]
+unsafe fn context_backtrace<C>(e: Ref<ErrorImpl>) -> Option<&Backtrace>
+where
+ C: 'static,
+{
+ let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref();
+ let backtrace = ErrorImpl::backtrace(unerased._object.error.inner.by_ref());
+ Some(backtrace)
+}
+
+// NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor
+// of raw pointers and `NonNull`.
+// 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,
+}
+
+// Reads the vtable out of `p`. This is the same as `p.as_ref().vtable`, but
+// avoids converting `p` into a reference.
+unsafe fn vtable(p: NonNull<ErrorImpl>) -> &'static ErrorVTable {
+ // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl.
+ *(p.as_ptr() as *const &'static ErrorVTable)
+}
+
+// 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) -> Ref<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 coercion.
+ Ref::new(self).cast::<ErrorImpl>()
+ }
+}
+
+impl ErrorImpl {
+ pub(crate) unsafe fn error(this: Ref<Self>) -> &(dyn StdError + Send + Sync + 'static) {
+ // Use vtable to attach E's native StdError vtable for the right
+ // original type E.
+ (vtable(this.ptr).object_ref)(this).deref()
+ }
+
+ #[cfg(feature = "std")]
+ pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
+ // Use vtable to attach E's native StdError vtable for the right
+ // original type E.
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ return (vtable(this.ptr).object_ref)(this.by_ref())
+ .by_mut()
+ .deref_mut();
+
+ #[cfg(anyhow_no_ptr_addr_of)]
+ return (vtable(this.ptr).object_mut)(this);
+ }
+
+ #[cfg(any(backtrace, feature = "backtrace"))]
+ pub(crate) unsafe fn backtrace(this: Ref<Self>) -> &Backtrace {
+ // This unwrap can only panic if the underlying error's backtrace method
+ // is nondeterministic, which would only happen in maliciously
+ // constructed code.
+ this.deref()
+ .backtrace
+ .as_ref()
+ .or_else(|| {
+ #[cfg(backtrace)]
+ return Self::error(this).request_ref::<Backtrace>();
+ #[cfg(not(backtrace))]
+ return (vtable(this.ptr).object_backtrace)(this);
+ })
+ .expect("backtrace capture failed")
+ }
+
+ #[cfg(backtrace)]
+ unsafe fn provide<'a>(this: Ref<'a, Self>, demand: &mut Demand<'a>) {
+ if let Some(backtrace) = &this.deref().backtrace {
+ demand.provide_ref(backtrace);
+ }
+ Self::error(this).provide(demand);
+ }
+
+ #[cold]
+ pub(crate) unsafe fn chain(this: Ref<Self>) -> Chain {
+ Chain::new(Self::error(this))
+ }
+}
+
+impl<E> StdError for ErrorImpl<E>
+where
+ E: StdError,
+{
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ unsafe { ErrorImpl::error(self.erase()).source() }
+ }
+
+ #[cfg(backtrace)]
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ unsafe { ErrorImpl::provide(self.erase(), demand) }
+ }
+}
+
+impl<E> Debug for ErrorImpl<E>
+where
+ E: Debug,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ unsafe { ErrorImpl::debug(self.erase(), formatter) }
+ }
+}
+
+impl<E> Display for ErrorImpl<E>
+where
+ E: Display,
+{
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) }
+ }
+}
+
+impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
+ #[cold]
+ fn from(error: Error) -> Self {
+ let outer = ManuallyDrop::new(error);
+ unsafe {
+ // Use vtable to attach ErrorImpl<E>'s native StdError vtable for
+ // the right original type E.
+ (vtable(outer.inner.ptr).object_boxed)(outer.inner)
+ }
+ }
+}
+
+impl From<Error> for Box<dyn StdError + Send + 'static> {
+ fn from(error: Error) -> Self {
+ Box::<dyn StdError + Send + Sync>::from(error)
+ }
+}
+
+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..03d8fd3940
--- /dev/null
+++ b/third_party/rust/anyhow/src/fmt.rs
@@ -0,0 +1,155 @@
+use crate::chain::Chain;
+use crate::error::ErrorImpl;
+use crate::ptr::Ref;
+use core::fmt::{self, Debug, Write};
+
+impl ErrorImpl {
+ pub(crate) unsafe fn display(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", Self::error(this))?;
+
+ if f.alternate() {
+ for cause in Self::chain(this).skip(1) {
+ write!(f, ": {}", cause)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) unsafe fn debug(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result {
+ let error = Self::error(this);
+
+ 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(any(backtrace, feature = "backtrace"))]
+ {
+ use crate::backtrace::BacktraceStatus;
+
+ let backtrace = Self::backtrace(this);
+ if let BacktraceStatus::Captured = backtrace.status() {
+ let mut backtrace = backtrace.to_string();
+ write!(f, "\n\n")?;
+ if backtrace.starts_with("stack backtrace:") {
+ // Capitalize to match "Caused by:"
+ backtrace.replace_range(0..1, "S");
+ } else {
+ // "stack backtrace:" prefix was removed in
+ // https://github.com/rust-lang/backtrace-rs/pull/286
+ writeln!(f, "Stack backtrace:")?;
+ }
+ backtrace.truncate(backtrace.trim_end().len());
+ write!(f, "{}", 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..f47fe44ba2
--- /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;
+
+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 {
+ #[cold]
+ 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 {
+ #[cold]
+ 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 {
+ #[cold]
+ 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..e570d6e9e3
--- /dev/null
+++ b/third_party/rust/anyhow/src/lib.rs
@@ -0,0 +1,680 @@
+//! [![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&logo=docs.rs
+//!
+//! <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, or stable with `features = ["backtrace"]`, 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(())
+//! # }
+//! ```
+//!
+//! A `bail!` macro is provided as a shorthand for the same early return.
+//!
+//! ```
+//! # use anyhow::{bail, Result};
+//! #
+//! # fn demo() -> Result<()> {
+//! # let missing = "...";
+//! bail!("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.69")]
+#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![deny(dead_code, unused_imports, unused_mut)]
+#![allow(
+ clippy::doc_markdown,
+ clippy::enum_glob_use,
+ clippy::explicit_auto_deref,
+ clippy::missing_errors_doc,
+ clippy::missing_panics_doc,
+ clippy::module_name_repetitions,
+ clippy::must_use_candidate,
+ clippy::needless_doctest_main,
+ clippy::new_ret_no_self,
+ clippy::redundant_else,
+ clippy::return_self_not_must_use,
+ clippy::unused_self,
+ clippy::used_underscore_binding,
+ clippy::wildcard_imports,
+ clippy::wrong_self_convention
+)]
+
+extern crate alloc;
+
+#[macro_use]
+mod backtrace;
+mod chain;
+mod context;
+mod ensure;
+mod error;
+mod fmt;
+mod kind;
+mod macros;
+mod ptr;
+mod wrapper;
+
+use crate::error::ErrorImpl;
+use crate::ptr::Own;
+use core::fmt::Display;
+
+#[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)
+/// ```
+///
+/// and if there is a backtrace available:
+///
+/// ```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(())
+/// }
+/// ```
+#[cfg_attr(not(doc), repr(transparent))]
+pub struct Error {
+ inner: Own<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")]
+#[cfg_attr(doc_cfg, doc(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)
+/// ```
+///
+/// Refer to the [Display representations] documentation for other forms in
+/// which this context chain can be rendered.
+///
+/// [Display representations]: Error#display-representations
+///
+/// <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;
+}
+
+/// Equivalent to Ok::<_, anyhow::Error>(value).
+///
+/// This simplifies creation of an anyhow::Result in places where type inference
+/// cannot deduce the `E` type of the result &mdash; without needing to write
+/// `Ok::<_, anyhow::Error>(value)`.
+///
+/// One might think that `anyhow::Result::Ok(value)` would work in such cases
+/// but it does not.
+///
+/// ```console
+/// error[E0282]: type annotations needed for `std::result::Result<i32, E>`
+/// --> src/main.rs:11:13
+/// |
+/// 11 | let _ = anyhow::Result::Ok(1);
+/// | - ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result`
+/// | |
+/// | consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified
+/// ```
+#[allow(non_snake_case)]
+pub fn Ok<T>(t: T) -> Result<T> {
+ Result::Ok(t)
+}
+
+// Not public API. Referenced by macro-generated code.
+#[doc(hidden)]
+pub mod __private {
+ use crate::Error;
+ use alloc::fmt;
+ use core::fmt::Arguments;
+
+ pub use crate::ensure::{BothDebug, NotBothDebug};
+ pub use alloc::format;
+ pub use core::result::Result::Err;
+ pub use core::{concat, format_args, stringify};
+
+ #[doc(hidden)]
+ pub mod kind {
+ pub use crate::kind::{AdhocKind, TraitKind};
+
+ #[cfg(feature = "std")]
+ pub use crate::kind::BoxedKind;
+ }
+
+ #[doc(hidden)]
+ #[inline]
+ #[cold]
+ pub fn format_err(args: Arguments) -> Error {
+ #[cfg(anyhow_no_fmt_arguments_as_str)]
+ let fmt_arguments_as_str = None::<&str>;
+ #[cfg(not(anyhow_no_fmt_arguments_as_str))]
+ let fmt_arguments_as_str = args.as_str();
+
+ if let Some(message) = fmt_arguments_as_str {
+ // anyhow!("literal"), can downcast to &'static str
+ Error::msg(message)
+ } else {
+ // anyhow!("interpolate {var}"), can downcast to String
+ Error::msg(fmt::format(args))
+ }
+ }
+
+ #[doc(hidden)]
+ #[inline]
+ #[cold]
+ #[must_use]
+ pub fn must_use(error: Error) -> Error {
+ error
+ }
+}
diff --git a/third_party/rust/anyhow/src/macros.rs b/third_party/rust/anyhow/src/macros.rs
new file mode 100644
index 0000000000..6dd22743b7
--- /dev/null
+++ b/third_party/rust/anyhow/src/macros.rs
@@ -0,0 +1,231 @@
+/// Return early with an error.
+///
+/// This macro is equivalent to `return Err(`[`anyhow!($args...)`][anyhow!]`)`.
+///
+/// The surrounding function's or closure's return value is required to be
+/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
+///
+/// [anyhow!]: crate::anyhow
+///
+/// # 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(`[`anyhow!($args...)`][anyhow!]`); }`.
+///
+/// The surrounding function's or closure's return value is required to be
+/// `Result<_,`[`anyhow::Error`][crate::Error]`>`.
+///
+/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
+/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
+/// rather than panicking.
+///
+/// [anyhow!]: crate::anyhow
+///
+/// # 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(())
+/// # }
+/// ```
+#[cfg(doc)]
+#[macro_export]
+macro_rules! ensure {
+ ($cond:expr $(,)?) => {
+ if !$cond {
+ return $crate::__private::Err($crate::Error::msg(
+ $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`")
+ ));
+ }
+ };
+ ($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)*));
+ }
+ };
+}
+
+#[cfg(not(doc))]
+#[macro_export]
+macro_rules! ensure {
+ ($($tt:tt)*) => {
+ $crate::__parse_ensure!(
+ /* state */ 0
+ /* stack */ ()
+ /* bail */ ($($tt)*)
+ /* fuel */ (~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~)
+ /* parse */ {()}
+ /* dup */ ($($tt)*)
+ /* rest */ $($tt)*
+ )
+ };
+}
+
+/// Construct an ad-hoc error from a string or existing non-`anyhow` error
+/// value.
+///
+/// This evaluates to an [`Error`][crate::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`.
+///
+/// If called with a single argument whose type implements `std::error::Error`
+/// (in addition to `Debug` and `Display`, which are always required), then that
+/// Error impl's `source` is preserved as the `source` of the resulting
+/// `anyhow::Error`.
+///
+/// # 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 $(,)?) => {
+ $crate::__private::must_use({
+ let error = $crate::__private::format_err($crate::__private::format_args!($msg));
+ error
+ })
+ };
+ ($err:expr $(,)?) => {
+ $crate::__private::must_use({
+ use $crate::__private::kind::*;
+ let error = match $err {
+ error => (&error).anyhow_kind().new(error),
+ };
+ error
+ })
+ };
+ ($fmt:expr, $($arg:tt)*) => {
+ $crate::Error::msg($crate::__private::format!($fmt, $($arg)*))
+ };
+}
+
+// Not public API. This is used in the implementation of some of the other
+// macros, in which the must_use call is not needed because the value is known
+// to be used.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __anyhow {
+ ($msg:literal $(,)?) => ({
+ let error = $crate::__private::format_err($crate::__private::format_args!($msg));
+ error
+ });
+ ($err:expr $(,)?) => ({
+ use $crate::__private::kind::*;
+ let error = match $err {
+ error => (&error).anyhow_kind().new(error),
+ };
+ error
+ });
+ ($fmt:expr, $($arg:tt)*) => {
+ $crate::Error::msg($crate::__private::format!($fmt, $($arg)*))
+ };
+}
diff --git a/third_party/rust/anyhow/src/ptr.rs b/third_party/rust/anyhow/src/ptr.rs
new file mode 100644
index 0000000000..c7fe488b6f
--- /dev/null
+++ b/third_party/rust/anyhow/src/ptr.rs
@@ -0,0 +1,199 @@
+use alloc::boxed::Box;
+use core::marker::PhantomData;
+use core::ptr::NonNull;
+
+#[repr(transparent)]
+pub struct Own<T>
+where
+ T: ?Sized,
+{
+ pub ptr: NonNull<T>,
+}
+
+unsafe impl<T> Send for Own<T> where T: ?Sized {}
+
+unsafe impl<T> Sync for Own<T> where T: ?Sized {}
+
+impl<T> Copy for Own<T> where T: ?Sized {}
+
+impl<T> Clone for Own<T>
+where
+ T: ?Sized,
+{
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<T> Own<T>
+where
+ T: ?Sized,
+{
+ pub fn new(ptr: Box<T>) -> Self {
+ Own {
+ ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) },
+ }
+ }
+
+ pub fn cast<U: CastTo>(self) -> Own<U::Target> {
+ Own {
+ ptr: self.ptr.cast(),
+ }
+ }
+
+ pub unsafe fn boxed(self) -> Box<T> {
+ Box::from_raw(self.ptr.as_ptr())
+ }
+
+ pub fn by_ref(&self) -> Ref<T> {
+ Ref {
+ ptr: self.ptr,
+ lifetime: PhantomData,
+ }
+ }
+
+ pub fn by_mut(&mut self) -> Mut<T> {
+ Mut {
+ ptr: self.ptr,
+ lifetime: PhantomData,
+ }
+ }
+}
+
+#[repr(transparent)]
+pub struct Ref<'a, T>
+where
+ T: ?Sized,
+{
+ pub ptr: NonNull<T>,
+ lifetime: PhantomData<&'a T>,
+}
+
+impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {}
+
+impl<'a, T> Clone for Ref<'a, T>
+where
+ T: ?Sized,
+{
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a, T> Ref<'a, T>
+where
+ T: ?Sized,
+{
+ pub fn new(ptr: &'a T) -> Self {
+ Ref {
+ ptr: NonNull::from(ptr),
+ lifetime: PhantomData,
+ }
+ }
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ pub fn from_raw(ptr: NonNull<T>) -> Self {
+ Ref {
+ ptr,
+ lifetime: PhantomData,
+ }
+ }
+
+ pub fn cast<U: CastTo>(self) -> Ref<'a, U::Target> {
+ Ref {
+ ptr: self.ptr.cast(),
+ lifetime: PhantomData,
+ }
+ }
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ pub fn by_mut(self) -> Mut<'a, T> {
+ Mut {
+ ptr: self.ptr,
+ lifetime: PhantomData,
+ }
+ }
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ pub fn as_ptr(self) -> *const T {
+ self.ptr.as_ptr() as *const T
+ }
+
+ pub unsafe fn deref(self) -> &'a T {
+ &*self.ptr.as_ptr()
+ }
+}
+
+#[repr(transparent)]
+pub struct Mut<'a, T>
+where
+ T: ?Sized,
+{
+ pub ptr: NonNull<T>,
+ lifetime: PhantomData<&'a mut T>,
+}
+
+impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {}
+
+impl<'a, T> Clone for Mut<'a, T>
+where
+ T: ?Sized,
+{
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a, T> Mut<'a, T>
+where
+ T: ?Sized,
+{
+ #[cfg(anyhow_no_ptr_addr_of)]
+ pub fn new(ptr: &'a mut T) -> Self {
+ Mut {
+ ptr: NonNull::from(ptr),
+ lifetime: PhantomData,
+ }
+ }
+
+ pub fn cast<U: CastTo>(self) -> Mut<'a, U::Target> {
+ Mut {
+ ptr: self.ptr.cast(),
+ lifetime: PhantomData,
+ }
+ }
+
+ #[cfg(not(anyhow_no_ptr_addr_of))]
+ pub fn by_ref(self) -> Ref<'a, T> {
+ Ref {
+ ptr: self.ptr,
+ lifetime: PhantomData,
+ }
+ }
+
+ pub fn extend<'b>(self) -> Mut<'b, T> {
+ Mut {
+ ptr: self.ptr,
+ lifetime: PhantomData,
+ }
+ }
+
+ pub unsafe fn deref_mut(self) -> &'a mut T {
+ &mut *self.ptr.as_ptr()
+ }
+}
+
+impl<'a, T> Mut<'a, T> {
+ pub unsafe fn read(self) -> T {
+ self.ptr.as_ptr().read()
+ }
+}
+
+// Force turbofish on all calls of `.cast::<U>()`.
+pub trait CastTo {
+ type Target;
+}
+
+impl<T> CastTo for T {
+ type Target = T;
+}
diff --git a/third_party/rust/anyhow/src/wrapper.rs b/third_party/rust/anyhow/src/wrapper.rs
new file mode 100644
index 0000000000..5f18a50313
--- /dev/null
+++ b/third_party/rust/anyhow/src/wrapper.rs
@@ -0,0 +1,81 @@
+use crate::StdError;
+use core::fmt::{self, Debug, Display};
+
+#[cfg(backtrace)]
+use std::any::Demand;
+
+#[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 {
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
+ self.0.source()
+ }
+
+ #[cfg(backtrace)]
+ fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ self.0.provide(demand);
+ }
+}
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..7974a6249e
--- /dev/null
+++ b/third_party/rust/anyhow/tests/compiletest.rs
@@ -0,0 +1,7 @@
+#[rustversion::attr(not(nightly), ignore)]
+#[cfg_attr(miri, 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..7da4bf55a1
--- /dev/null
+++ b/third_party/rust/anyhow/tests/drop/mod.rs
@@ -0,0 +1,53 @@
+#![allow(clippy::module_name_repetitions)]
+
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::sync::atomic::{AtomicBool, Ordering};
+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(Ordering::Relaxed)
+ }
+}
+
+#[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, Ordering::Relaxed);
+ 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..fb1fb132d5
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_boxed.rs
@@ -0,0 +1,45 @@
+#![allow(
+ // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
+ clippy::nonstandard_macro_braces,
+)]
+
+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..c8b901ab41
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_chain.rs
@@ -0,0 +1,69 @@
+use anyhow::{anyhow, Chain, 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!((4, Some(4)), chain.size_hint());
+ assert_eq!("3", chain.next().unwrap().to_string());
+ assert_eq!(3, chain.len());
+ assert_eq!((3, Some(3)), chain.size_hint());
+ assert_eq!("0", chain.next_back().unwrap().to_string());
+ assert_eq!(2, chain.len());
+ assert_eq!((2, Some(2)), chain.size_hint());
+ assert_eq!("2", chain.next().unwrap().to_string());
+ assert_eq!(1, chain.len());
+ assert_eq!((1, Some(1)), chain.size_hint());
+ assert_eq!("1", chain.next_back().unwrap().to_string());
+ assert_eq!(0, chain.len());
+ assert_eq!((0, Some(0)), chain.size_hint());
+ assert!(chain.next().is_none());
+}
+
+#[test]
+fn test_default() {
+ let mut c = Chain::default();
+ assert!(c.next().is_none());
+}
+
+#[test]
+#[allow(clippy::redundant_clone)]
+fn test_clone() {
+ let e = error();
+ let mut chain = e.chain().clone();
+ 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());
+}
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..2053fc9e57
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_context.rs
@@ -0,0 +1,172 @@
+#![allow(
+ // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
+ clippy::nonstandard_macro_braces,
+)]
+
+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,
+ #[allow(dead_code)]
+ 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());
+}
+
+#[test]
+fn test_root_cause() {
+ let (err, _) = make_chain();
+
+ assert_eq!(err.root_cause().to_string(), "no such file or directory");
+}
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..6da171d1b8
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_convert.rs
@@ -0,0 +1,46 @@
+#![allow(clippy::unnecessary_wraps)]
+
+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>::from(error);
+ assert_eq!("oh no!", box_dyn.to_string());
+ drop(box_dyn);
+ assert!(has_dropped.get());
+}
+
+#[test]
+fn test_convert_send() {
+ let has_dropped = Flag::new();
+ let error = Error::new(DetectDrop::new(&has_dropped));
+ let box_dyn = Box::<dyn StdError + Send>::from(error);
+ assert_eq!("oh no!", box_dyn.to_string());
+ drop(box_dyn);
+ assert!(has_dropped.get());
+}
+
+#[test]
+fn test_convert_send_sync() {
+ 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..b4470d551a
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_downcast.rs
@@ -0,0 +1,123 @@
+#![allow(clippy::assertions_on_result_states, clippy::wildcard_imports)]
+
+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(),
+ );
+
+ let mut bailed = bail_fmt().unwrap_err();
+ *bailed.downcast_mut::<String>().unwrap() = "clobber".to_string();
+ assert_eq!(bailed.downcast_ref::<String>().unwrap(), "clobber");
+ assert_eq!(bailed.downcast_mut::<String>().unwrap(), "clobber");
+ assert_eq!(bailed.downcast::<String>().unwrap(), "clobber");
+}
+
+#[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_as_ref() {
+ let error = bail_error().unwrap_err();
+ let ref_dyn: &dyn StdError = error.as_ref();
+ assert_eq!("oh no!", ref_dyn.to_string());
+ let ref_dyn_send_sync: &(dyn StdError + Send + Sync) = error.as_ref();
+ assert_eq!("oh no!", ref_dyn_send_sync.to_string());
+}
+
+#[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_ensure.rs b/third_party/rust/anyhow/tests/test_ensure.rs
new file mode 100644
index 0000000000..de867f7fe8
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_ensure.rs
@@ -0,0 +1,718 @@
+#![allow(
+ clippy::bool_to_int_with_if,
+ clippy::diverging_sub_expression,
+ clippy::if_same_then_else,
+ clippy::ifs_same_cond,
+ clippy::items_after_statements,
+ clippy::let_and_return,
+ clippy::match_bool,
+ clippy::never_loop,
+ clippy::overly_complex_bool_expr,
+ clippy::redundant_closure_call,
+ clippy::redundant_pattern_matching,
+ clippy::too_many_lines,
+ clippy::unit_arg,
+ clippy::while_immutable_condition,
+ clippy::zero_ptr,
+ irrefutable_let_patterns
+)]
+
+use self::Enum::Generic;
+use anyhow::{anyhow, ensure, Chain, Error, Result};
+use std::fmt::{self, Debug};
+use std::iter;
+use std::marker::{PhantomData, PhantomData as P};
+use std::mem;
+use std::ops::Add;
+use std::ptr;
+
+struct S;
+
+impl<T> Add<T> for S {
+ type Output = bool;
+ fn add(self, rhs: T) -> Self::Output {
+ let _ = rhs;
+ false
+ }
+}
+
+trait Trait: Sized {
+ const V: usize = 0;
+ fn t(self, i: i32) -> i32 {
+ i
+ }
+}
+
+impl<T> Trait for T {}
+
+enum Enum<T: ?Sized> {
+ #[allow(dead_code)]
+ Thing(PhantomData<T>),
+ Generic,
+}
+
+impl<T: ?Sized> PartialEq for Enum<T> {
+ fn eq(&self, rhs: &Self) -> bool {
+ mem::discriminant(self) == mem::discriminant(rhs)
+ }
+}
+
+impl<T: ?Sized> Debug for Enum<T> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Generic")
+ }
+}
+
+#[track_caller]
+fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
+ let actual = result().unwrap_err().to_string();
+
+ // In general different rustc versions will format the interpolated lhs and
+ // rhs $:expr fragment with insignificant differences in whitespace or
+ // punctuation, so we check the message in full against nightly and do just
+ // a cursory test on older toolchains.
+ if rustversion::cfg!(nightly) && !cfg!(miri) {
+ assert_eq!(actual, expected);
+ } else {
+ assert_eq!(actual.contains(" vs "), expected.contains(" vs "));
+ }
+}
+
+#[test]
+fn test_recursion() {
+ // Must not blow the default #[recursion_limit], which is 128.
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false |
+ false | false | false | false | false | false | false | false | false
+ ));
+
+ test().unwrap_err();
+}
+
+#[test]
+fn test_low_precedence_control_flow() {
+ #[allow(unreachable_code)]
+ let test = || {
+ let val = loop {
+ // Break has lower precedence than the comparison operators so the
+ // expression here is `S + (break (1 == 1))`. It would be bad if the
+ // ensure macro partitioned this input into `(S + break 1) == (1)`
+ // because that means a different thing than what was written.
+ ensure!(S + break 1 == 1);
+ };
+ Ok(val)
+ };
+
+ assert!(test().unwrap());
+}
+
+#[test]
+fn test_low_precedence_binary_operator() {
+ // Must not partition as `false == (true && false)`.
+ let test = || Ok(ensure!(false == true && false));
+ assert_err(test, "Condition failed: `false == true && false`");
+
+ // But outside the root level, it is fine.
+ let test = || Ok(ensure!(while false == true && false {} < ()));
+ assert_err(
+ test,
+ "Condition failed: `while false == true && false {} < ()` (() vs ())",
+ );
+}
+
+#[test]
+fn test_closure() {
+ // Must not partition as `(S + move) || (1 == 1)` by treating move as an
+ // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the
+ // closure precedence.
+ let test = || Ok(ensure!(S + move || 1 == 1));
+ assert_err(test, "Condition failed: `S + (move || 1 == 1)`");
+
+ let test = || Ok(ensure!(S + || 1 == 1));
+ assert_err(test, "Condition failed: `S + (|| 1 == 1)`");
+
+ // Must not partition as `S + ((move | ()) | 1) == 1` by treating those
+ // pipes as bitwise-or.
+ let test = || Ok(ensure!(S + move |()| 1 == 1));
+ assert_err(test, "Condition failed: `S + (move |()| 1 == 1)`");
+
+ let test = || Ok(ensure!(S + |()| 1 == 1));
+ assert_err(test, "Condition failed: `S + (|()| 1 == 1)`");
+}
+
+#[test]
+fn test_unary() {
+ let mut x = &1;
+ let test = || Ok(ensure!(*x == 2));
+ assert_err(test, "Condition failed: `*x == 2` (1 vs 2)");
+
+ let test = || Ok(ensure!(!x == 1));
+ assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)");
+
+ let test = || Ok(ensure!(-x == 1));
+ assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)");
+
+ let test = || Ok(ensure!(&x == &&2));
+ assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)");
+
+ let test = || Ok(ensure!(&mut x == *&&mut &2));
+ assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)");
+}
+
+#[test]
+fn test_if() {
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if false {}.t(1) == 2));
+ assert_err(test, "Condition failed: `if false {}.t(1) == 2` (1 vs 2)");
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if false {} else {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `if false {} else {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `if false {} else if false {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `if let 1 = 2 {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `if let 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `if let 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)",
+ );
+}
+
+#[test]
+fn test_loop() {
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(1 + loop { break 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `1 + loop { break 1 } == 1` (2 vs 1)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `1 + 'a: loop { break 'a 1 } == 1` (2 vs 1)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(while false {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `while false {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(while let None = Some(1) {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `while let None = Some(1) {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(for _x in iter::once(0) {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `for _x in iter::once(0) {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(for | _x in iter::once(0) {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `for _x in iter::once(0) {}.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(for true | false in iter::empty() {}.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `for true | false in iter::empty() {}.t(1) == 2` (1 vs 2)",
+ );
+}
+
+#[test]
+fn test_match() {
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(match 1 == 1 { true => 1, false => 0 } == 2));
+ assert_err(
+ test,
+ "Condition failed: `match 1 == 1 { true => 1, false => 0, } == 2` (1 vs 2)",
+ );
+}
+
+#[test]
+fn test_atom() {
+ let test = || Ok(ensure!([false, false].len() > 3));
+ assert_err(
+ test,
+ "Condition failed: `[false, false].len() > 3` (2 vs 3)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!({ let x = 1; x } >= 3));
+ assert_err(test, "Condition failed: `{ let x = 1; x } >= 3` (1 vs 3)");
+
+ let test = || Ok(ensure!(S + async { 1 } == true));
+ assert_err(
+ test,
+ "Condition failed: `S + async { 1 } == true` (false vs true)",
+ );
+
+ let test = || Ok(ensure!(S + async move { 1 } == true));
+ assert_err(
+ test,
+ "Condition failed: `S + async move { 1 } == true` (false vs true)",
+ );
+
+ let x = &1;
+ let test = || Ok(ensure!(S + unsafe { ptr::read(x) } == true));
+ assert_err(
+ test,
+ "Condition failed: `S + unsafe { ptr::read(x) } == true` (false vs true)",
+ );
+}
+
+#[test]
+fn test_path() {
+ let test = || Ok(ensure!(crate::S.t(1) == 2));
+ assert_err(test, "Condition failed: `crate::S.t(1) == 2` (1 vs 2)");
+
+ let test = || Ok(ensure!(::anyhow::Error::root_cause.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `::anyhow::Error::root_cause.t(1) == 2` (1 vs 2)",
+ );
+
+ let test = || Ok(ensure!(Error::msg::<&str>.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(Error::msg::<&str,>.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
+ );
+
+ let test = || Ok(ensure!(Error::msg::<<str as ToOwned>::Owned>.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `Error::msg::<<str as ToOwned>::Owned>.t(1) == 2` (1 vs 2)",
+ );
+
+ let test = || Ok(ensure!(Chain::<'static>::new.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(Chain::<'static,>::new.t(1) == 2));
+ assert_err(
+ test,
+ "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
+ );
+
+ fn f<const I: isize>() {}
+ let test = || Ok(ensure!(f::<1>() != ()));
+ assert_err(test, "Condition failed: `f::<1>() != ()` (() vs ())");
+ let test = || Ok(ensure!(f::<-1>() != ()));
+ assert_err(test, "Condition failed: `f::<-1>() != ()` (() vs ())");
+
+ fn g<T, const I: isize>() {}
+ let test = || Ok(ensure!(g::<u8, 1>() != ()));
+ assert_err(test, "Condition failed: `g::<u8, 1>() != ()` (() vs ())");
+ let test = || Ok(ensure!(g::<u8, -1>() != ()));
+ assert_err(test, "Condition failed: `g::<u8, -1>() != ()` (() vs ())");
+
+ #[derive(PartialOrd, PartialEq, Debug)]
+ enum E<'a, T> {
+ #[allow(dead_code)]
+ T(&'a T),
+ U,
+ }
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(E::U::<>>E::U::<u8>));
+ assert_err(test, "Condition failed: `E::U::<> > E::U::<u8>` (U vs U)");
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(E::U::<u8>>E::U));
+ assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(E::U::<u8,>>E::U));
+ assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
+
+ let test = || Ok(ensure!(Generic::<dyn Debug + Sync> != Generic));
+ assert_err(
+ test,
+ "Condition failed: `Generic::<dyn Debug + Sync> != Generic` (Generic vs Generic)",
+ );
+
+ let test = || Ok(ensure!(Generic::<dyn Fn() + Sync> != Generic));
+ assert_err(
+ test,
+ "Condition failed: `Generic::<dyn Fn() + Sync> != Generic` (Generic vs Generic)",
+ );
+
+ #[rustfmt::skip]
+ let test = || {
+ Ok(ensure!(
+ Generic::<dyn Fn::() + ::std::marker::Sync> != Generic
+ ))
+ };
+ assert_err(
+ test,
+ "Condition failed: `Generic::<dyn Fn() + ::std::marker::Sync> != Generic` (Generic vs Generic)",
+ );
+}
+
+#[test]
+fn test_macro() {
+ let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1));
+ assert_err(
+ test,
+ "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)",
+ );
+
+ let test = || Ok(ensure!(vec![1].len() < 1));
+ assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)");
+
+ let test = || Ok(ensure!(stringify! {} != ""));
+ assert_err(
+ test,
+ "Condition failed: `stringify! {} != \"\"` (\"\" vs \"\")",
+ );
+}
+
+#[test]
+fn test_trailer() {
+ let test = || Ok(ensure!((|| 1)() == 2));
+ assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)");
+
+ let test = || Ok(ensure!(b"hmm"[1] == b'c'));
+ assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)");
+
+ let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
+ assert_err(
+ test,
+ "Condition failed: `PhantomData::<u8> {} != PhantomData` (PhantomData<u8> vs PhantomData<u8>)",
+ );
+
+ let result = Ok::<_, Error>(1);
+ let test = || Ok(ensure!(result? == 2));
+ assert_err(test, "Condition failed: `result? == 2` (1 vs 2)");
+
+ let test = || Ok(ensure!((2, 3).1 == 2));
+ assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)");
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!((2, (3, 4)). 1.1 == 2));
+ assert_err(test, "Condition failed: `(2, (3, 4)).1.1 == 2` (4 vs 2)");
+
+ let err = anyhow!("");
+ let test = || Ok(ensure!(err.is::<&str>() == false));
+ assert_err(
+ test,
+ "Condition failed: `err.is::<&str>() == false` (true vs false)",
+ );
+
+ let test = || Ok(ensure!(err.is::<<str as ToOwned>::Owned>() == true));
+ assert_err(
+ test,
+ "Condition failed: `err.is::<<str as ToOwned>::Owned>() == true` (false vs true)",
+ );
+}
+
+#[test]
+fn test_whitespace() {
+ #[derive(Debug)]
+ pub struct Point {
+ pub x: i32,
+ pub y: i32,
+ }
+
+ let point = Point { x: 0, y: 0 };
+ let test = || Ok(ensure!("" == format!("{:#?}", point)));
+ assert_err(
+ test,
+ "Condition failed: `\"\" == format!(\"{:#?}\", point)`",
+ );
+}
+
+#[test]
+fn test_too_long() {
+ let test = || Ok(ensure!("" == "x".repeat(10)));
+ assert_err(
+ test,
+ "Condition failed: `\"\" == \"x\".repeat(10)` (\"\" vs \"xxxxxxxxxx\")",
+ );
+
+ let test = || Ok(ensure!("" == "x".repeat(80)));
+ assert_err(test, "Condition failed: `\"\" == \"x\".repeat(80)`");
+}
+
+#[test]
+fn test_as() {
+ let test = || Ok(ensure!('\0' as u8 > 1));
+ assert_err(test, "Condition failed: `'\\0' as u8 > 1` (0 vs 1)");
+
+ let test = || Ok(ensure!('\0' as ::std::primitive::u8 > 1));
+ assert_err(
+ test,
+ "Condition failed: `'\\0' as ::std::primitive::u8 > 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(&[0] as &[i32] == [1]));
+ assert_err(
+ test,
+ "Condition failed: `&[0] as &[i32] == [1]` ([0] vs [1])",
+ );
+
+ let test = || Ok(ensure!(0 as *const () as *mut _ == 1 as *mut ()));
+ assert_err(
+ test,
+ "Condition failed: `0 as *const () as *mut _ == 1 as *mut ()` (0x0 vs 0x1)",
+ );
+
+ let s = "";
+ let test = || Ok(ensure!(s as &str != s));
+ assert_err(test, "Condition failed: `s as &str != s` (\"\" vs \"\")");
+
+ let test = || Ok(ensure!(&s as &&str != &s));
+ assert_err(test, "Condition failed: `&s as &&str != &s` (\"\" vs \"\")");
+
+ let test = || Ok(ensure!(s as &'static str != s));
+ assert_err(
+ test,
+ "Condition failed: `s as &'static str != s` (\"\" vs \"\")",
+ );
+
+ let test = || Ok(ensure!(&s as &&'static str != &s));
+ assert_err(
+ test,
+ "Condition failed: `&s as &&'static str != &s` (\"\" vs \"\")",
+ );
+
+ let m: &mut str = Default::default();
+ let test = || Ok(ensure!(m as &mut str != s));
+ assert_err(
+ test,
+ "Condition failed: `m as &mut str != s` (\"\" vs \"\")",
+ );
+
+ let test = || Ok(ensure!(&m as &&mut str != &s));
+ assert_err(
+ test,
+ "Condition failed: `&m as &&mut str != &s` (\"\" vs \"\")",
+ );
+
+ let test = || Ok(ensure!(&m as &&'static mut str != &s));
+ assert_err(
+ test,
+ "Condition failed: `&m as &&'static mut str != &s` (\"\" vs \"\")",
+ );
+
+ let f = || {};
+ let test = || Ok(ensure!(f as fn() as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as fn() as usize * 0 != 0` (0 vs 0)",
+ );
+
+ let test = || Ok(ensure!(f as fn() -> () as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as fn() -> () as usize * 0 != 0` (0 vs 0)",
+ );
+
+ let test = || Ok(ensure!(f as for<'a> fn() as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as for<'a> fn() as usize * 0 != 0` (0 vs 0)",
+ );
+
+ let test = || Ok(ensure!(f as unsafe fn() as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as unsafe fn() as usize * 0 != 0` (0 vs 0)",
+ );
+
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(f as extern "Rust" fn() as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as extern \"Rust\" fn() as usize * 0 != 0` (0 vs 0)",
+ );
+
+ extern "C" fn extern_fn() {}
+ #[rustfmt::skip]
+ let test = || Ok(ensure!(extern_fn as extern fn() as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `extern_fn as extern fn() as usize * 0 != 0` (0 vs 0)",
+ );
+
+ let f = || -> ! { panic!() };
+ let test = || Ok(ensure!(f as fn() -> ! as usize * 0 != 0));
+ assert_err(
+ test,
+ "Condition failed: `f as fn() -> ! as usize * 0 != 0` (0 vs 0)",
+ );
+
+ trait EqDebug<T>: PartialEq<T> + Debug {
+ type Assoc;
+ }
+
+ impl<S, T> EqDebug<T> for S
+ where
+ S: PartialEq<T> + Debug,
+ {
+ type Assoc = bool;
+ }
+
+ let test = || Ok(ensure!(&0 as &dyn EqDebug<i32, Assoc = bool> != &0));
+ assert_err(
+ test,
+ "Condition failed: `&0 as &dyn EqDebug<i32, Assoc = bool> != &0` (0 vs 0)",
+ );
+
+ let test = || {
+ Ok(ensure!(
+ PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData
+ ))
+ };
+ assert_err(
+ test,
+ "Condition failed: `PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData` (PhantomData<i32> vs PhantomData<i32>)",
+ );
+
+ macro_rules! int {
+ (...) => {
+ u8
+ };
+ }
+
+ let test = || Ok(ensure!(0 as int!(...) != 0));
+ assert_err(test, "Condition failed: `0 as int!(...) != 0` (0 vs 0)");
+
+ let test = || Ok(ensure!(0 as int![...] != 0));
+ assert_err(test, "Condition failed: `0 as int![...] != 0` (0 vs 0)");
+
+ let test = || Ok(ensure!(0 as int! {...} != 0));
+ assert_err(test, "Condition failed: `0 as int! { ... } != 0` (0 vs 0)");
+}
+
+#[test]
+fn test_pat() {
+ let test = || Ok(ensure!(if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let -1..=1 = 0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let -1..=1 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let &0 = &0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let &0 = &0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let &&0 = &&0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let &&0 = &&0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let &mut 0 = &mut 0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let &mut 0 = &mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let (0, 1) = (0, 1) { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let (0, 1) = (0, 1) { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let [0] = b"\0" { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let [0] = b\"\\0\" { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let p = PhantomData::<u8>;
+ let test = || Ok(ensure!(if let P::<u8> {} = p { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let P::<u8> {} = p { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(if let ::std::marker::PhantomData = p {} != ()));
+ assert_err(
+ test,
+ "Condition failed: `if let ::std::marker::PhantomData = p {} != ()` (() vs ())",
+ );
+
+ let test = || Ok(ensure!(if let <S as Trait>::V = 0 { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let <S as Trait>::V = 0 { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+
+ let test = || Ok(ensure!(for _ in iter::once(()) {} != ()));
+ assert_err(
+ test,
+ "Condition failed: `for _ in iter::once(()) {} != ()` (() vs ())",
+ );
+
+ let test = || Ok(ensure!(if let stringify!(x) = "x" { 0 } else { 1 } == 1));
+ assert_err(
+ test,
+ "Condition failed: `if let stringify!(x) = \"x\" { 0 } else { 1 } == 1` (0 vs 1)",
+ );
+}
diff --git a/third_party/rust/anyhow/tests/test_ffi.rs b/third_party/rust/anyhow/tests/test_ffi.rs
new file mode 100644
index 0000000000..0321fc1b05
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_ffi.rs
@@ -0,0 +1,18 @@
+#![deny(improper_ctypes, improper_ctypes_definitions)]
+
+use anyhow::anyhow;
+
+#[no_mangle]
+pub extern "C" fn anyhow1(err: anyhow::Error) {
+ println!("{:?}", err);
+}
+
+#[no_mangle]
+pub extern "C" fn anyhow2(err: &mut Option<anyhow::Error>) {
+ *err = Some(anyhow!("ffi error"));
+}
+
+#[no_mangle]
+pub extern "C" fn anyhow3() -> Option<anyhow::Error> {
+ Some(anyhow!("ffi error"))
+}
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..a3342ab776
--- /dev/null
+++ b/third_party/rust/anyhow/tests/test_macros.rs
@@ -0,0 +1,80 @@
+#![allow(
+ clippy::assertions_on_result_states,
+ clippy::eq_op,
+ clippy::items_after_statements,
+ clippy::needless_pass_by_value,
+ clippy::shadow_unrelated,
+ clippy::wildcard_imports
+)]
+
+mod common;
+
+use self::common::*;
+use anyhow::{anyhow, ensure};
+use std::cell::Cell;
+use std::future;
+
+#[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());
+
+ let f = || {
+ ensure!(v + v == 1);
+ Ok(())
+ };
+ assert_eq!(
+ f().unwrap_err().to_string(),
+ "Condition failed: `v + v == 1` (2 vs 1)",
+ );
+}
+
+#[test]
+fn test_temporaries() {
+ fn require_send_sync(_: impl Send + Sync) {}
+
+ require_send_sync(async {
+ // If anyhow hasn't dropped any temporary format_args it creates by the
+ // time it's done evaluating, those will stick around until the
+ // semicolon, which is on the other side of the await point, making the
+ // enclosing future non-Send.
+ future::ready(anyhow!("...")).await;
+ });
+
+ fn message(cell: Cell<&str>) -> &str {
+ cell.get()
+ }
+
+ require_send_sync(async {
+ future::ready(anyhow!(message(Cell::new("...")))).await;
+ });
+}
+
+#[test]
+fn test_brace_escape() {
+ let err = anyhow!("unterminated ${{..}} expression");
+ assert_eq!("unterminated ${..} expression", err.to_string());
+}
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/chained-comparison.rs b/third_party/rust/anyhow/tests/ui/chained-comparison.rs
new file mode 100644
index 0000000000..4521b51c8c
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/chained-comparison.rs
@@ -0,0 +1,8 @@
+use anyhow::{ensure, Result};
+
+fn main() -> Result<()> {
+ // `ensure!` must not partition this into `(false) == (false == true)`
+ // because Rust doesn't ordinarily allow this form of expression.
+ ensure!(false == false == true);
+ Ok(())
+}
diff --git a/third_party/rust/anyhow/tests/ui/chained-comparison.stderr b/third_party/rust/anyhow/tests/ui/chained-comparison.stderr
new file mode 100644
index 0000000000..2a4c66508a
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/chained-comparison.stderr
@@ -0,0 +1,10 @@
+error: comparison operators cannot be chained
+ --> tests/ui/chained-comparison.rs:6:19
+ |
+6 | ensure!(false == false == true);
+ | ^^ ^^
+ |
+help: split the comparison into two
+ |
+6 | ensure!(false == false && false == true);
+ | ++++++++
diff --git a/third_party/rust/anyhow/tests/ui/empty-ensure.rs b/third_party/rust/anyhow/tests/ui/empty-ensure.rs
new file mode 100644
index 0000000000..139b743bbf
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/empty-ensure.rs
@@ -0,0 +1,6 @@
+use anyhow::{ensure, Result};
+
+fn main() -> Result<()> {
+ ensure!();
+ Ok(())
+}
diff --git a/third_party/rust/anyhow/tests/ui/empty-ensure.stderr b/third_party/rust/anyhow/tests/ui/empty-ensure.stderr
new file mode 100644
index 0000000000..bf0229a2b2
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/empty-ensure.stderr
@@ -0,0 +1,12 @@
+error: unexpected end of macro invocation
+ --> tests/ui/empty-ensure.rs:4:5
+ |
+4 | ensure!();
+ | ^^^^^^^^^ missing tokens in macro arguments
+ |
+note: while trying to match meta-variable `$cond:expr`
+ --> src/ensure.rs
+ |
+ | ($cond:expr $(,)?) => {
+ | ^^^^^^^^^^
+ = note: this error originates in the macro `$crate::__parse_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/anyhow/tests/ui/must-use.rs b/third_party/rust/anyhow/tests/ui/must-use.rs
new file mode 100644
index 0000000000..ea4e58f55e
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/must-use.rs
@@ -0,0 +1,11 @@
+#![deny(unused_must_use)]
+
+use anyhow::anyhow;
+
+fn main() -> anyhow::Result<()> {
+ if true {
+ // meant to write bail!
+ anyhow!("it failed");
+ }
+ Ok(())
+}
diff --git a/third_party/rust/anyhow/tests/ui/must-use.stderr b/third_party/rust/anyhow/tests/ui/must-use.stderr
new file mode 100644
index 0000000000..e10bde40f7
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/must-use.stderr
@@ -0,0 +1,12 @@
+error: unused return value of `anyhow::__private::must_use` that must be used
+ --> tests/ui/must-use.rs:8:9
+ |
+8 | anyhow!("it failed");
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> tests/ui/must-use.rs:1:9
+ |
+1 | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)
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..1ddf768639
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/no-impl.stderr
@@ -0,0 +1,31 @@
+error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its trait bounds were not satisfied
+ --> tests/ui/no-impl.rs:7:13
+ |
+4 | struct Error;
+ | ------------
+ | |
+ | doesn't satisfy `Error: Into<anyhow::Error>`
+ | doesn't satisfy `Error: anyhow::kind::TraitKind`
+ | doesn't satisfy `Error: std::fmt::Display`
+...
+7 | let _ = anyhow!(Error);
+ | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Error: Into<anyhow::Error>`
+ which is required by `Error: anyhow::kind::TraitKind`
+ `Error: std::fmt::Display`
+ which is required by `&Error: anyhow::kind::AdhocKind`
+ `&Error: Into<anyhow::Error>`
+ which is required by `&Error: anyhow::kind::TraitKind`
+note: the traits `Into` and `std::fmt::Display` must be implemented
+ --> $RUST/core/src/fmt/mod.rs
+ |
+ | pub trait Display {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ ::: $RUST/core/src/convert/mod.rs
+ |
+ | pub trait Into<T>: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/third_party/rust/anyhow/tests/ui/temporary-value.rs b/third_party/rust/anyhow/tests/ui/temporary-value.rs
new file mode 100644
index 0000000000..803809b238
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/temporary-value.rs
@@ -0,0 +1,5 @@
+use anyhow::anyhow;
+
+fn main() {
+ let _ = anyhow!(&String::new());
+}
diff --git a/third_party/rust/anyhow/tests/ui/temporary-value.stderr b/third_party/rust/anyhow/tests/ui/temporary-value.stderr
new file mode 100644
index 0000000000..dc27c4981f
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/temporary-value.stderr
@@ -0,0 +1,9 @@
+error[E0716]: temporary value dropped while borrowed
+ --> tests/ui/temporary-value.rs:4:22
+ |
+4 | let _ = anyhow!(&String::new());
+ | ---------^^^^^^^^^^^^^-
+ | | |
+ | | creates a temporary value which is freed while still in use
+ | temporary value is freed at the end of this statement
+ | argument requires that borrow lasts for `'static`
diff --git a/third_party/rust/anyhow/tests/ui/wrong-interpolation.rs b/third_party/rust/anyhow/tests/ui/wrong-interpolation.rs
new file mode 100644
index 0000000000..b870ca713d
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/wrong-interpolation.rs
@@ -0,0 +1,5 @@
+use anyhow::{bail, Result};
+
+fn main() -> Result<()> {
+ bail!("{} not found");
+}
diff --git a/third_party/rust/anyhow/tests/ui/wrong-interpolation.stderr b/third_party/rust/anyhow/tests/ui/wrong-interpolation.stderr
new file mode 100644
index 0000000000..55a2964113
--- /dev/null
+++ b/third_party/rust/anyhow/tests/ui/wrong-interpolation.stderr
@@ -0,0 +1,5 @@
+error: 1 positional argument in format string, but no arguments were given
+ --> tests/ui/wrong-interpolation.rs:4:12
+ |
+4 | bail!("{} not found");
+ | ^^