anyhow-1.0.86/.cargo_vcs_info.json0000644000000001360000000000100124350ustar { "git": { "sha1": "8ea1819c4c7829d0eb09e54a52806f382b8d445b" }, "path_in_vcs": "" }anyhow-1.0.86/.github/FUNDING.yml000064400000000000000000000000201046102023000143720ustar 00000000000000github: dtolnay anyhow-1.0.86/.github/workflows/ci.yml000064400000000000000000000073151046102023000157460ustar 00000000000000name: CI on: push: pull_request: workflow_dispatch: schedule: [cron: "40 1 * * *"] permissions: contents: read env: RUSTFLAGS: -Dwarnings jobs: pre_ci: uses: dtolnay/.github/.github/workflows/pre_ci.yml@master test: name: Rust ${{matrix.rust}} needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: [nightly, beta, stable, 1.70.0] timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} components: rust-src - name: Enable type layout randomization run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV if: matrix.rust == 'nightly' - name: Enable nightly-only tests run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=anyhow_nightly_testing >> $GITHUB_ENV if: matrix.rust == 'nightly' - run: cargo test - run: cargo check --no-default-features - run: cargo check --features backtrace build: name: Rust ${{matrix.rust}} needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: [1.65.0, 1.52.0, 1.51.0, 1.50.0, 1.39.0] timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} components: rust-src - run: cargo check - run: cargo check --no-default-features - run: cargo check --features backtrace if: matrix.rust != '1.52.0' && matrix.rust != '1.51.0' && matrix.rust != '1.50.0' && matrix.rust != '1.39.0' minimal: name: Minimal versions needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked --features backtrace windows: name: Windows needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: windows-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rust-src - run: cargo check --features backtrace doc: name: Documentation needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 env: RUSTDOCFLAGS: -Dwarnings steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly with: components: rust-src - uses: dtolnay/install@cargo-docs-rs - run: cargo docs-rs clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly with: components: clippy, rust-src - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic miri: name: Miri needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - run: cargo miri test env: MIRIFLAGS: -Zmiri-strict-provenance outdated: name: Outdated runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 anyhow-1.0.86/.gitignore000064400000000000000000000000361046102023000132140ustar 00000000000000/target **/*.rs.bk Cargo.lock anyhow-1.0.86/Cargo.toml0000644000000046600000000000100104410ustar # 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.86" authors = ["David Tolnay "] build = "build.rs" autobins = false autoexamples = false autotests = false autobenches = false 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] rustdoc-args = [ "--cfg", "doc_cfg", "--generate-link-to-definition", ] targets = ["x86_64-unknown-linux-gnu"] [lib] name = "anyhow" path = "src/lib.rs" doc-scrape-examples = false [[test]] name = "test_ensure" path = "tests/test_ensure.rs" [[test]] name = "test_chain" path = "tests/test_chain.rs" [[test]] name = "test_fmt" path = "tests/test_fmt.rs" [[test]] name = "test_source" path = "tests/test_source.rs" [[test]] name = "test_repr" path = "tests/test_repr.rs" [[test]] name = "test_autotrait" path = "tests/test_autotrait.rs" [[test]] name = "test_boxed" path = "tests/test_boxed.rs" [[test]] name = "test_backtrace" path = "tests/test_backtrace.rs" [[test]] name = "test_convert" path = "tests/test_convert.rs" [[test]] name = "test_macros" path = "tests/test_macros.rs" [[test]] name = "compiletest" path = "tests/compiletest.rs" [[test]] name = "test_context" path = "tests/test_context.rs" [[test]] name = "test_ffi" path = "tests/test_ffi.rs" [[test]] name = "test_downcast" path = "tests/test_downcast.rs" [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 = "2.0" features = ["full"] [dev-dependencies.thiserror] version = "1.0.45" [dev-dependencies.trybuild] version = "1.0.66" features = ["diff"] [features] default = ["std"] std = [] anyhow-1.0.86/Cargo.toml.orig000064400000000000000000000021661046102023000141210ustar 00000000000000[package] name = "anyhow" version = "1.0.86" authors = ["David Tolnay "] categories = ["rust-patterns", "no-std"] description = "Flexible concrete Error type built on std::error::Error" documentation = "https://docs.rs/anyhow" edition = "2018" keywords = ["error", "error-handling"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/anyhow" rust-version = "1.39" [features] default = ["std"] std = [] [dependencies] # On compilers older than 1.65, features=["backtrace"] may be used to enable # backtraces via the `backtrace` crate. This feature has no effect on 1.65+ # besides bringing in an unused dependency, as `std::backtrace` is always # preferred. backtrace = { version = "0.3.51", optional = true } [dev-dependencies] futures = { version = "0.3", default-features = false } rustversion = "1.0.6" syn = { version = "2.0", features = ["full"] } thiserror = "1.0.45" trybuild = { version = "1.0.66", features = ["diff"] } [lib] doc-scrape-examples = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] anyhow-1.0.86/LICENSE-APACHE000064400000000000000000000227731046102023000131640ustar 00000000000000 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 anyhow-1.0.86/LICENSE-MIT000064400000000000000000000017771046102023000126750ustar 00000000000000Permission 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. anyhow-1.0.86/README.md000064400000000000000000000137001046102023000125050ustar 00000000000000Anyhow ¯\\\_(°ペ)\_/¯ ========================== [github](https://github.com/dtolnay/anyhow) [crates.io](https://crates.io/crates/anyhow) [docs.rs](https://docs.rs/anyhow) [build status](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+*
## Details - Use `Result`, or equivalently `anyhow::Result`, 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 { let config = std::fs::read_to_string("cluster.json")?; let map: ClusterMap = serde_json::from_str(&config)?; Ok(map) } ``` [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html - 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::() { Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), None => Err(error), } ``` - If using Rust ≥ 1.65, 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`. [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables - 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); ```
## No-std support In no_std mode, almost all of the same API is 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.
## 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
## 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
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
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. anyhow-1.0.86/build/probe.rs000064400000000000000000000016761046102023000140130ustar 00000000000000// This code exercises the surface area that we expect of the Error generic // member access API. If the current toolchain is able to compile it, then // anyhow is able to provide backtrace support. #![feature(error_generic_member_access)] use std::backtrace::Backtrace; use std::error::{self, Error, Request}; use std::fmt::{self, Debug, Display}; struct MyError(Thing); struct Thing; impl Debug for MyError { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } } impl Display for MyError { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } } impl Error for MyError { fn provide<'a>(&'a self, request: &mut Request<'a>) { request.provide_ref(&self.0); } } const _: fn(&dyn Error) -> Option<&Backtrace> = |err| error::request_ref::(err); // Include in sccache cache key. const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); anyhow-1.0.86/build.rs000064400000000000000000000144341046102023000127000ustar 00000000000000use std::env; use std::ffi::OsString; use std::iter; use std::path::Path; use std::process::{self, Command, Stdio}; use std::str; #[cfg(all(feature = "backtrace", not(feature = "std")))] compile_error! { "`backtrace` feature without `std` feature is not supported" } fn main() { let mut error_generic_member_access = false; if cfg!(feature = "std") { println!("cargo:rerun-if-changed=build/probe.rs"); let consider_rustc_bootstrap; if compile_probe(false) { // This is a nightly or dev compiler, so it supports unstable // features regardless of RUSTC_BOOTSTRAP. No need to rerun build // script if RUSTC_BOOTSTRAP is changed. error_generic_member_access = true; consider_rustc_bootstrap = false; } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { if compile_probe(true) { // This is a stable or beta compiler for which the user has set // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build // script if they change it. error_generic_member_access = true; consider_rustc_bootstrap = true; } else if rustc_bootstrap == "1" { // This compiler does not support the generic member access API // in the form that anyhow expects. No need to pay attention to // RUSTC_BOOTSTRAP. error_generic_member_access = false; consider_rustc_bootstrap = false; } else { // This is a stable or beta compiler for which RUSTC_BOOTSTRAP // is set to restrict the use of unstable features by this // crate. error_generic_member_access = false; consider_rustc_bootstrap = true; } } else { // Without RUSTC_BOOTSTRAP, this compiler does not support the // generic member access API in the form that anyhow expects, but // try again if the user turns on unstable features. error_generic_member_access = false; consider_rustc_bootstrap = true; } if error_generic_member_access { println!("cargo:rustc-cfg=std_backtrace"); println!("cargo:rustc-cfg=error_generic_member_access"); } if consider_rustc_bootstrap { println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); } } let rustc = match rustc_minor_version() { Some(rustc) => rustc, None => return, }; if rustc >= 80 { println!("cargo:rustc-check-cfg=cfg(anyhow_nightly_testing)"); println!("cargo:rustc-check-cfg=cfg(anyhow_no_fmt_arguments_as_str)"); println!("cargo:rustc-check-cfg=cfg(anyhow_no_ptr_addr_of)"); println!("cargo:rustc-check-cfg=cfg(anyhow_no_unsafe_op_in_unsafe_fn_lint)"); println!("cargo:rustc-check-cfg=cfg(doc_cfg)"); println!("cargo:rustc-check-cfg=cfg(error_generic_member_access)"); println!("cargo:rustc-check-cfg=cfg(std_backtrace)"); } if rustc < 51 { // core::ptr::addr_of // https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#stabilized-apis println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of"); } if rustc < 52 { // core::fmt::Arguments::as_str // https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html#stabilized-apis println!("cargo:rustc-cfg=anyhow_no_fmt_arguments_as_str"); // #![deny(unsafe_op_in_unsafe_fn)] // https://github.com/rust-lang/rust/issues/71668 println!("cargo:rustc-cfg=anyhow_no_unsafe_op_in_unsafe_fn_lint"); } if !error_generic_member_access && cfg!(feature = "std") && rustc >= 65 { // std::backtrace::Backtrace // https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#stabilized-apis println!("cargo:rustc-cfg=std_backtrace"); } } fn compile_probe(rustc_bootstrap: bool) -> bool { if env::var_os("RUSTC_STAGE").is_some() { // We are running inside rustc bootstrap. This is a highly non-standard // environment with issues such as: // // https://github.com/rust-lang/cargo/issues/11138 // https://github.com/rust-lang/rust/issues/114839 // // Let's just not use nightly features here. return false; } let rustc = cargo_env_var("RUSTC"); let out_dir = cargo_env_var("OUT_DIR"); let probefile = Path::new("build").join("probe.rs"); let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let rustc_workspace_wrapper = env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let mut rustc = rustc_wrapper .into_iter() .chain(rustc_workspace_wrapper) .chain(iter::once(rustc)); let mut cmd = Command::new(rustc.next().unwrap()); cmd.args(rustc); if !rustc_bootstrap { cmd.env_remove("RUSTC_BOOTSTRAP"); } cmd.stderr(Stdio::null()) .arg("--edition=2018") .arg("--crate-name=anyhow") .arg("--crate-type=lib") .arg("--emit=dep-info,metadata") .arg("--cap-lints=allow") .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); } } } match cmd.status() { Ok(status) => status.success(), Err(_) => false, } } fn rustc_minor_version() -> Option { let rustc = cargo_env_var("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() } fn cargo_env_var(key: &str) -> OsString { env::var_os(key).unwrap_or_else(|| { eprintln!( "Environment variable ${} is not set during execution of build script", key, ); process::exit(1); }) } anyhow-1.0.86/rust-toolchain.toml000064400000000000000000000000461046102023000150750ustar 00000000000000[toolchain] components = ["rust-src"] anyhow-1.0.86/src/backtrace.rs000064400000000000000000000313351046102023000143060ustar 00000000000000#[cfg(std_backtrace)] pub(crate) use std::backtrace::{Backtrace, BacktraceStatus}; #[cfg(all(not(std_backtrace), feature = "backtrace"))] pub(crate) use self::capture::{Backtrace, BacktraceStatus}; #[cfg(not(any(std_backtrace, feature = "backtrace")))] pub(crate) enum Backtrace {} #[cfg(std_backtrace)] macro_rules! impl_backtrace { () => { std::backtrace::Backtrace }; } #[cfg(all(not(std_backtrace), feature = "backtrace"))] macro_rules! impl_backtrace { () => { impl core::fmt::Debug + core::fmt::Display }; } #[cfg(any(std_backtrace, feature = "backtrace"))] macro_rules! backtrace { () => { Some(crate::backtrace::Backtrace::capture()) }; } #[cfg(not(any(std_backtrace, feature = "backtrace")))] macro_rules! backtrace { () => { None }; } #[cfg(error_generic_member_access)] macro_rules! backtrace_if_absent { ($err:expr) => { match std::error::request_ref::($err as &dyn std::error::Error) { Some(_) => None, None => backtrace!(), } }; } #[cfg(all( feature = "std", not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] macro_rules! backtrace_if_absent { ($err:expr) => { backtrace!() }; } #[cfg(all(feature = "std", not(std_backtrace), not(feature = "backtrace")))] macro_rules! backtrace_if_absent { ($err:expr) => { None }; } #[cfg(all(not(std_backtrace), feature = "backtrace"))] mod capture { use alloc::borrow::{Cow, ToOwned as _}; use alloc::vec::Vec; 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::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, } struct BacktraceFrame { frame: Frame, symbols: Vec, } struct BacktraceSymbol { name: Option>, filename: Option, lineno: Option, colno: Option, } enum BytesOrWide { Bytes(Vec), Wide(Vec), } impl Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str(""), Inner::Disabled => return fmt.write_str(""), 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: ")?; } 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, } 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 = 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("")).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("").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() {} _assert::(); } anyhow-1.0.86/src/chain.rs000064400000000000000000000046501046102023000134510ustar 00000000000000use self::ChainState::*; use crate::StdError; #[cfg(feature = "std")] use alloc::vec::{self, 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 { 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) { let len = self.len(); (len, Some(len)) } } #[cfg(feature = "std")] impl DoubleEndedIterator for Chain<'_> { fn next_back(&mut self) -> Option { 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(), }, } } } anyhow-1.0.86/src/context.rs000064400000000000000000000110141046102023000140430ustar 00000000000000use crate::error::ContextError; use crate::{Context, Error, StdError}; use core::convert::Infallible; use core::fmt::{self, Debug, Display, Write}; #[cfg(error_generic_member_access)] use std::error::Request; mod ext { use super::*; pub trait StdError { fn ext_context(self, context: C) -> Error where C: Display + Send + Sync + 'static; } #[cfg(feature = "std")] impl StdError for E where E: std::error::Error + Send + Sync + 'static, { fn ext_context(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(self, context: C) -> Error where C: Display + Send + Sync + 'static, { self.context(context) } } } impl Context for Result where E: ext::StdError + Send + Sync + 'static, { fn context(self, context: C) -> Result 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(self, context: F) -> Result 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 { /// # const IGNORE: &str = stringify! { /// ... /// # }; /// # unimplemented!() /// } /// /// fn demo() -> Result<()> { /// let t = maybe_get().context("there is no T")?; /// # const IGNORE: &str = stringify! { /// ... /// # }; /// # unimplemented!() /// } /// ``` impl Context for Option { fn context(self, context: C) -> Result 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(self, context: F) -> Result where C: Display + Send + Sync + 'static, F: FnOnce() -> C, { match self { Some(ok) => Ok(ok), None => Err(Error::from_display(context(), backtrace!())), } } } impl Debug for ContextError 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 Display for ContextError where C: Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.context, f) } } impl StdError for ContextError where C: Display, E: StdError + 'static, { fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(&self.error) } #[cfg(error_generic_member_access)] fn provide<'a>(&'a self, request: &mut Request<'a>) { StdError::provide(&self.error, request); } } impl StdError for ContextError where C: Display, { fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) } #[cfg(error_generic_member_access)] fn provide<'a>(&'a self, request: &mut Request<'a>) { Error::provide(&self.error, request); } } struct Quoted(C); impl Debug for Quoted 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 Sealed for Result where E: ext::StdError {} impl Sealed for Option {} } anyhow-1.0.86/src/ensure.rs000064400000000000000000001415431046102023000136730ustar 00000000000000use 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 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 NotBothDebug for &(A, B) { fn __dispatch_ensure(self, msg: &'static str) -> Error { Error::msg(msg) } } struct Buf { bytes: [MaybeUninit; 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::(), 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::(), 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)*} ($lifetime:tt $colon:tt $($dup:tt)*) $label:lifetime : $($rest:tt)*) => { $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $lifetime $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)*} ($const:tt $block:tt $($dup:tt)*) const {$($body:tt)*} $($rest:tt)*) => { // TODO: this is mostly useless due to https://github.com/rust-lang/rust/issues/86730 $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $const $block) $($parse)*} ($($rest)*) $($rest)*) }; (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $literal) $($parse)*} ($($rest)*) $($rest)*) }; // path expressions (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i: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)*} ($ident:tt $($dup:tt)*) $i: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 $langle:tt $($dup:tt)*) :: << $($rest:tt)*) => { $crate::__parse_ensure!(type (qpath (tpath (arglist (epath $stack)))) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) }; (epath $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt :: <- - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $larrow:tt $($dup:tt)*) :: <- $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) }; (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i: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 (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) $parse $dup $($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 $langle:tt $($dup:tt)*) . $i:ident :: << $($rest:tt)*) => { $crate::__parse_ensure!(type (qpath (tpath (arglist (atom $stack)))) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $langle) $($parse)*} ($($rest)*) $($rest)*) }; (atom $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt . $i:ident :: <- - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $larrow:tt $($dup:tt)*) . $i:ident :: <- $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) }; (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $field:tt $($dup:tt)*) . $i: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)*} $dup:tt . - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (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 $lifetime:tt $mut:tt $($dup:tt)*) & $l:lifetime mut $($rest:tt)*) => { $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime $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 $lifetime:tt $($dup:tt)*) & $l:lifetime $($rest:tt)*) => { $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime) $($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 $lifetime:tt $mut:tt $($dup:tt)*) && $l:lifetime mut $($rest:tt)*) => { $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime $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 $lifetime:tt $($dup:tt)*) && $l:lifetime $($rest:tt)*) => { $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $lifetime) $($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)*} $dup:tt unsafe extern - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (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)*} $dup:tt extern - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt $abi:tt 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 $ident:tt $($dup:tt)*) :: $i: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)*} ($ident:tt $($dup:tt)*) $i: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)*} ($langle:tt $($dup:tt)*) << $($rest:tt)*) => { $crate::__parse_ensure!(type (qpath (tpath (arglist (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::__fallback_ensure!($($bail)*) }; (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($larrow:tt $($dup:tt)*) <- $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $larrow) $($parse)*} ($($dup)*) $($dup)*) }; (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 $langle:tt $($dup:tt)*) :: << $($rest:tt)*) => { $crate::__parse_ensure!(type (qpath (tpath (arglist (tpath $stack)))) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) }; (tpath $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt :: <- - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $larrow:tt $($dup:tt)*) :: <- $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons $larrow) $($parse)*} ($($dup)*) $($dup)*) }; (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $ident:tt $($dup:tt)*) :: $i: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 (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $ident:tt $($dup:tt)*) >> :: $i:ident $($rest:tt)*) => { $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle $colons $ident) $($parse)*} ($($rest)*) $($rest)*) }; (qpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $ident:tt $($dup:tt)*) > :: $i: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 $ident:tt $($dup:tt)*) + :: $i: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 $ident:tt $($dup:tt)*) + $i:ident $($rest:tt)*) => { $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $ident) $($parse)*} ($($rest)*) $($rest)*) }; (object (split ($pop:ident $stack:tt)) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) $parse $dup $($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 (split ($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)*} ($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)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) {($($buf)*) $($parse)*} ($rangle $($rest)*) $rangle $($rest)*) }; (generic $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(generic $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($dup)*) $($dup)*) }; (generic $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $literal) $($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)*} ($lifetime:tt $($dup:tt)*) $l:lifetime $($rest:tt)*) => { $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $lifetime) $($parse)*} ($($rest)*) $($rest)*) }; (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assoc:tt $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 (split ($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)*} ($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)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { $crate::__parse_ensure!($pop (split $stack) $bail ($($fuel)*) {($($buf)*) $($parse)*} ($rangle $($rest)*) $rangle $($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 - - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($dup)*) $($dup)*) }; (pat $stack:tt ($($bail:tt)*) (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt - $($rest:tt)*) => { $crate::__fallback_ensure!($($bail)*) }; (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($literal:tt $($dup:tt)*) $lit:literal $($rest:tt)*) => { $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $literal) $($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 $ident:tt $($dup:tt)*) :: $i: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)*} ($ident:tt $($dup:tt)*) $i: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)*) }; // 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 (split ()) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => { $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)* > ) > } ($($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 (split $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($rangle:tt $($dup:tt)*) >> $($rest:tt)*) => { $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($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)*) }; // 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)*) }; // 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 $crate::__private::not($cond) { return $crate::__private::Err($crate::Error::msg( $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`") )); } }; ($cond:expr, $msg:literal $(,)?) => { if $crate::__private::not($cond) { return $crate::__private::Err($crate::__anyhow!($msg)); } }; ($cond:expr, $err:expr $(,)?) => { if $crate::__private::not($cond) { return $crate::__private::Err($crate::__anyhow!($err)); } }; ($cond:expr, $fmt:expr, $($arg:tt)*) => { if $crate::__private::not($cond) { return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)); } }; } anyhow-1.0.86/src/error.rs000064400000000000000000001065551046102023000135270ustar 00000000000000use 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; 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(error_generic_member_access)] use std::error::{self, Request}; #[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(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 { /// # unimplemented!() /// # } /// # } /// # /// # use ffi::{Input, Output}; /// # /// use anyhow::{Error, Result}; /// use futures::stream::{Stream, StreamExt, TryStreamExt}; /// /// async fn demo(stream: S) -> Result> /// where /// S: Stream, /// { /// stream /// .then(ffi::do_some_work) // returns Result /// .map_err(Error::msg) /// .try_collect() /// .await /// } /// ``` #[cold] #[must_use] pub fn msg(message: M) -> Self where M: Display + Debug + Send + Sync + 'static, { Error::from_adhoc(message, backtrace!()) } #[cfg(feature = "std")] #[cold] pub(crate) fn from_std(error: E, backtrace: Option) -> Self where E: StdError + Send + Sync + 'static, { let vtable = &ErrorVTable { object_drop: object_drop::, object_ref: object_ref::, #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::, object_boxed: object_boxed::, object_downcast: object_downcast::, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, #[cfg(all( not(error_generic_member_access), any(std_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(message: M, backtrace: Option) -> Self where M: Display + Debug + Send + Sync + 'static, { use crate::wrapper::MessageError; let error: MessageError = MessageError(message); let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: object_downcast::, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] object_backtrace: no_backtrace, }; // Safety: MessageError is repr(transparent) so it is okay for the // vtable to allow casting the MessageError to M. unsafe { Error::construct(error, vtable, backtrace) } } #[cold] pub(crate) fn from_display(message: M, backtrace: Option) -> Self where M: Display + Send + Sync + 'static, { use crate::wrapper::DisplayError; let error: DisplayError = DisplayError(message); let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: object_downcast::, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] object_backtrace: no_backtrace, }; // Safety: DisplayError is repr(transparent) so it is okay for the // vtable to allow casting the DisplayError to M. unsafe { Error::construct(error, vtable, backtrace) } } #[cfg(feature = "std")] #[cold] pub(crate) fn from_context(context: C, error: E, backtrace: Option) -> Self where C: Display + Send + Sync + 'static, E: StdError + Send + Sync + 'static, { let error: ContextError = ContextError { context, error }; let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: context_downcast::, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: context_downcast_mut::, object_drop_rest: context_drop_rest::, #[cfg(all( not(error_generic_member_access), any(std_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, backtrace: Option, ) -> Self { use crate::wrapper::BoxedError; let error = BoxedError(error); let vtable = &ErrorVTable { object_drop: object_drop::, object_ref: object_ref::, #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::, object_boxed: object_boxed::, object_downcast: object_downcast::>, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: object_downcast_mut::>, object_drop_rest: object_drop_front::>, #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] object_backtrace: no_backtrace, }; // Safety: BoxedError is repr(transparent) so it is okay for the vtable // to allow casting to Box. 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( error: E, vtable: &'static ErrorVTable, backtrace: Option, ) -> Self where E: StdError + Send + Sync + 'static, { let inner: Box> = 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> to // Box> except that the // result is a thin pointer. The necessary behavior for manipulating the // underlying ErrorImpl is preserved in the vtable provided by the // caller rather than a builtin fat pointer vtable. let inner = Own::new(inner).cast::(); 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 { /// # const IGNORE: &str = stringify! { /// ... /// # }; /// # unimplemented!() /// } /// /// pub fn parse(path: impl AsRef) -> Result { /// 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(self, context: C) -> Self where C: Display + Send + Sync + 'static, { let error: ContextError = ContextError { context, error: self, }; let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: context_chain_downcast::, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: context_chain_downcast_mut::, object_drop_rest: context_chain_drop_rest::, #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] object_backtrace: context_backtrace::, }; // 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 when using Rust ≥ /// 1.65. On older 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. The return type of this /// function on old compilers is `&(impl Debug + Display)`. /// /// ```toml /// [dependencies] /// anyhow = { version = "1.0", features = ["backtrace"] } /// ``` #[cfg(any(std_backtrace, 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 { /// for cause in error.chain() { /// if let Some(io_error) = cause.downcast_ref::() { /// 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 — 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(&self) -> bool where E: Display + Debug + Send + Sync + 'static, { self.downcast_ref::().is_some() } /// Attempt to downcast the error object to a concrete type. pub fn downcast(mut self) -> Result where E: Display + Debug + Send + Sync + 'static, { let target = TypeId::of::(); 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::().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::() { /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), /// None => Err(error), /// } /// # ; /// ``` pub fn downcast_ref(&self) -> Option<&E> where E: Display + Debug + Send + Sync + 'static, { let target = TypeId::of::(); 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::().deref()) } } /// Downcast this error object by mutable reference. pub fn downcast_mut(&mut self) -> Option<&mut E> where E: Display + Debug + Send + Sync + 'static, { let target = TypeId::of::(); 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::().deref_mut()) } } #[cfg(error_generic_member_access)] pub(crate) fn provide<'a>(&'a self, request: &mut Request<'a>) { unsafe { ErrorImpl::provide(self.inner.by_ref(), request) } } // 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. #[cfg(error_generic_member_access)] #[doc(hidden)] pub fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { Self::provide(self, request); } } #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl From 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), object_ref: unsafe fn(Ref) -> Ref, #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: unsafe fn(Mut) -> &mut (dyn StdError + Send + Sync + 'static), object_boxed: unsafe fn(Own) -> Box, object_downcast: unsafe fn(Ref, TypeId) -> Option>, #[cfg(anyhow_no_ptr_addr_of)] object_downcast_mut: unsafe fn(Mut, TypeId) -> Option>, object_drop_rest: unsafe fn(Own, TypeId), #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] object_backtrace: unsafe fn(Ref) -> Option<&Backtrace>, } // Safety: requires layout of *e to match ErrorImpl. unsafe fn object_drop(e: Own) { // Cast back to ErrorImpl so that the allocator receives the correct // Layout to deallocate the Box's memory. let unerased_own = e.cast::>(); drop(unsafe { unerased_own.boxed() }); } // Safety: requires layout of *e to match ErrorImpl. unsafe fn object_drop_front(e: Own, 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_own = e.cast::>>(); drop(unsafe { unerased_own.boxed() }); } // Safety: requires layout of *e to match ErrorImpl. unsafe fn object_ref(e: Ref) -> Ref where E: StdError + Send + Sync + 'static, { // Attach E's native StdError vtable onto a pointer to self._object. let unerased_ref = e.cast::>(); #[cfg(not(anyhow_no_ptr_addr_of))] return Ref::from_raw(unsafe { NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) }); #[cfg(anyhow_no_ptr_addr_of)] return Ref::new(unsafe { &unerased_ref.deref()._object }); } // Safety: requires layout of *e to match ErrorImpl, and for `e` to be derived // from a `&mut` #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] unsafe fn object_mut(e: Mut) -> &mut (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_mut = e.cast::>(); unsafe { &mut unerased_mut.deref_mut()._object } } // Safety: requires layout of *e to match ErrorImpl. unsafe fn object_boxed(e: Own) -> Box where E: StdError + Send + Sync + 'static, { // Attach ErrorImpl's native StdError vtable. The StdError impl is below. let unerased_own = e.cast::>(); unsafe { unerased_own.boxed() } } // Safety: requires layout of *e to match ErrorImpl. unsafe fn object_downcast(e: Ref, target: TypeId) -> Option> where E: 'static, { if TypeId::of::() == target { // Caller is looking for an E pointer and e is ErrorImpl, take a // pointer to its E field. let unerased_ref = e.cast::>(); #[cfg(not(anyhow_no_ptr_addr_of))] return Some( Ref::from_raw(unsafe { NonNull::new_unchecked(ptr::addr_of!((*unerased_ref.as_ptr())._object) as *mut E) }) .cast::<()>(), ); #[cfg(anyhow_no_ptr_addr_of)] return Some(Ref::new(unsafe { &unerased_ref.deref()._object }).cast::<()>()); } else { None } } // Safety: requires layout of *e to match ErrorImpl. #[cfg(anyhow_no_ptr_addr_of)] unsafe fn object_downcast_mut(e: Mut, target: TypeId) -> Option> where E: 'static, { if TypeId::of::() == target { // Caller is looking for an E pointer and e is ErrorImpl, take a // pointer to its E field. let unerased_mut = e.cast::>(); let unerased = unsafe { unerased_mut.deref_mut() }; Some(Mut::new(&mut unerased._object).cast::<()>()) } else { None } } #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] fn no_backtrace(e: Ref) -> Option<&Backtrace> { let _ = e; None } // Safety: requires layout of *e to match ErrorImpl>. #[cfg(feature = "std")] unsafe fn context_downcast(e: Ref, target: TypeId) -> Option> where C: 'static, E: 'static, { if TypeId::of::() == target { let unerased_ref = e.cast::>>(); let unerased = unsafe { unerased_ref.deref() }; Some(Ref::new(&unerased._object.context).cast::<()>()) } else if TypeId::of::() == target { let unerased_ref = e.cast::>>(); let unerased = unsafe { unerased_ref.deref() }; Some(Ref::new(&unerased._object.error).cast::<()>()) } else { None } } // Safety: requires layout of *e to match ErrorImpl>. #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] unsafe fn context_downcast_mut(e: Mut, target: TypeId) -> Option> where C: 'static, E: 'static, { if TypeId::of::() == target { let unerased_mut = e.cast::>>(); let unerased = unsafe { unerased_mut.deref_mut() }; Some(Mut::new(&mut unerased._object.context).cast::<()>()) } else if TypeId::of::() == target { let unerased_mut = e.cast::>>(); let unerased = unsafe { unerased_mut.deref_mut() }; Some(Mut::new(&mut unerased._object.error).cast::<()>()) } else { None } } // Safety: requires layout of *e to match ErrorImpl>. #[cfg(feature = "std")] unsafe fn context_drop_rest(e: Own, 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::() == target { let unerased_own = e.cast::, E>>>(); drop(unsafe { unerased_own.boxed() }); } else { let unerased_own = e.cast::>>>(); drop(unsafe { unerased_own.boxed() }); } } // Safety: requires layout of *e to match ErrorImpl>. unsafe fn context_chain_downcast(e: Ref, target: TypeId) -> Option> where C: 'static, { let unerased_ref = e.cast::>>(); let unerased = unsafe { unerased_ref.deref() }; if TypeId::of::() == 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; unsafe { (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) } } } // Safety: requires layout of *e to match ErrorImpl>. #[cfg(anyhow_no_ptr_addr_of)] unsafe fn context_chain_downcast_mut(e: Mut, target: TypeId) -> Option> where C: 'static, { let unerased_mut = e.cast::>>(); let unerased = unsafe { unerased_mut.deref_mut() }; if TypeId::of::() == 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; unsafe { (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target) } } } // Safety: requires layout of *e to match ErrorImpl>. unsafe fn context_chain_drop_rest(e: Own, 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::() == target { let unerased_own = e.cast::, Error>>>(); // Drop the entire rest of the data structure rooted in the next Error. drop(unsafe { unerased_own.boxed() }); } else { let unerased_own = e.cast::>>>(); let unerased = unsafe { unerased_own.boxed() }; // Read the Own from the next error. let inner = unerased._object.error.inner; drop(unerased); let vtable = unsafe { vtable(inner.ptr) }; // Recursively drop the next error using the same target typeid. unsafe { (vtable.object_drop_rest)(inner, target) }; } } // Safety: requires layout of *e to match ErrorImpl>. #[cfg(all( not(error_generic_member_access), any(std_backtrace, feature = "backtrace") ))] #[allow(clippy::unnecessary_wraps)] unsafe fn context_backtrace(e: Ref) -> Option<&Backtrace> where C: 'static, { let unerased_ref = e.cast::>>(); let unerased = unsafe { unerased_ref.deref() }; let backtrace = unsafe { 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 { vtable: &'static ErrorVTable, backtrace: Option, // 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) -> &'static ErrorVTable { // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl. unsafe { *(p.as_ptr() as *const &'static ErrorVTable) } } // repr C to ensure that ContextError has the same layout as // ContextError, E> and ContextError>. #[repr(C)] pub(crate) struct ContextError { pub context: C, pub error: E, } impl ErrorImpl { fn erase(&self) -> Ref { // 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::() } } impl ErrorImpl { pub(crate) unsafe fn error(this: Ref) -> &(dyn StdError + Send + Sync + 'static) { // Use vtable to attach E's native StdError vtable for the right // original type E. unsafe { (vtable(this.ptr).object_ref)(this).deref() } } #[cfg(feature = "std")] pub(crate) unsafe fn error_mut(this: Mut) -> &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 unsafe { (vtable(this.ptr).object_ref)(this.by_ref()) .by_mut() .deref_mut() }; #[cfg(anyhow_no_ptr_addr_of)] return unsafe { (vtable(this.ptr).object_mut)(this) }; } #[cfg(any(std_backtrace, feature = "backtrace"))] pub(crate) unsafe fn backtrace(this: Ref) -> &Backtrace { // This unwrap can only panic if the underlying error's backtrace method // is nondeterministic, which would only happen in maliciously // constructed code. unsafe { this.deref() } .backtrace .as_ref() .or_else(|| { #[cfg(error_generic_member_access)] return error::request_ref::(unsafe { Self::error(this) }); #[cfg(not(error_generic_member_access))] return unsafe { (vtable(this.ptr).object_backtrace)(this) }; }) .expect("backtrace capture failed") } #[cfg(error_generic_member_access)] unsafe fn provide<'a>(this: Ref<'a, Self>, request: &mut Request<'a>) { if let Some(backtrace) = unsafe { &this.deref().backtrace } { request.provide_ref(backtrace); } unsafe { Self::error(this) }.provide(request); } #[cold] pub(crate) unsafe fn chain(this: Ref) -> Chain { Chain::new(unsafe { Self::error(this) }) } } impl StdError for ErrorImpl where E: StdError, { fn source(&self) -> Option<&(dyn StdError + 'static)> { unsafe { ErrorImpl::error(self.erase()).source() } } #[cfg(error_generic_member_access)] fn provide<'a>(&'a self, request: &mut Request<'a>) { unsafe { ErrorImpl::provide(self.erase(), request) } } } impl Debug for ErrorImpl where E: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { unsafe { ErrorImpl::debug(self.erase(), formatter) } } } impl Display for ErrorImpl where E: Display, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) } } } impl From for Box { #[cold] fn from(error: Error) -> Self { let outer = ManuallyDrop::new(error); unsafe { // Use vtable to attach ErrorImpl's native StdError vtable for // the right original type E. (vtable(outer.inner.ptr).object_boxed)(outer.inner) } } } impl From for Box { fn from(error: Error) -> Self { Box::::from(error) } } impl From for Box { fn from(error: Error) -> Self { Box::::from(error) } } #[cfg(feature = "std")] impl AsRef for Error { fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) { &**self } } #[cfg(feature = "std")] impl AsRef for Error { fn as_ref(&self) -> &(dyn StdError + 'static) { &**self } } anyhow-1.0.86/src/fmt.rs000064400000000000000000000102451046102023000131520ustar 00000000000000use 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, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", unsafe { Self::error(this) })?; if f.alternate() { let chain = unsafe { Self::chain(this) }; for cause in chain.skip(1) { write!(f, ": {}", cause)?; } } Ok(()) } pub(crate) unsafe fn debug(this: Ref, f: &mut fmt::Formatter) -> fmt::Result { let error = unsafe { 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(std_backtrace, feature = "backtrace"))] { use crate::backtrace::BacktraceStatus; use alloc::string::ToString; let backtrace = unsafe { 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, started: bool, } impl 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::*; use alloc::string::String; #[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); } } anyhow-1.0.86/src/kind.rs000064400000000000000000000057121046102023000133140ustar 00000000000000// 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 AnyhowNew for T // where // T: Display + Debug + Send + Sync + 'static, // { // default fn new(self) -> Error { // /* no std error impl */ // } // } // // impl AnyhowNew for T // where // T: std::error::Error + Send + Sync + 'static, // { // fn new(self) -> Error { // /* use std error's source() and backtrace() */ // } // } // // Since specialization is not stable yet, instead we rely on autoref behavior // of method resolution to perform tagged dispatch. Here we have two traits // AdhocKind and TraitKind that both have an anyhow_kind() method. AdhocKind is // implemented whether or not the caller's type has a std error impl, while // TraitKind is implemented only when a std error impl does exist. The ambiguity // is resolved by AdhocKind requiring an extra autoref so that it has lower // precedence. // // The anyhow! macro will set up the call in this form: // // #[allow(unused_imports)] // use $crate::__private::{AdhocKind, TraitKind}; // let error = $msg; // (&error).anyhow_kind().new(error) use crate::Error; use core::fmt::{Debug, Display}; #[cfg(feature = "std")] use crate::StdError; #[cfg(feature = "std")] use alloc::boxed::Box; pub struct Adhoc; #[doc(hidden)] pub trait AdhocKind: Sized { #[inline] fn anyhow_kind(&self) -> Adhoc { Adhoc } } impl AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {} impl Adhoc { #[cold] pub fn new(self, message: M) -> Error where M: Display + Debug + Send + Sync + 'static, { Error::from_adhoc(message, backtrace!()) } } pub struct Trait; #[doc(hidden)] pub trait TraitKind: Sized { #[inline] fn anyhow_kind(&self) -> Trait { Trait } } impl TraitKind for E where E: Into {} impl Trait { #[cold] pub fn new(self, error: E) -> Error where E: Into, { error.into() } } #[cfg(feature = "std")] pub struct Boxed; #[cfg(feature = "std")] #[doc(hidden)] pub trait BoxedKind: Sized { #[inline] fn anyhow_kind(&self) -> Boxed { Boxed } } #[cfg(feature = "std")] impl BoxedKind for Box {} #[cfg(feature = "std")] impl Boxed { #[cold] pub fn new(self, error: Box) -> Error { let backtrace = backtrace_if_absent!(&*error); Error::from_boxed(error, backtrace) } } anyhow-1.0.86/src/lib.rs000064400000000000000000000513311046102023000131330ustar 00000000000000//! [![github]](https://github.com/dtolnay/anyhow) [![crates-io]](https://crates.io/crates/anyhow) [![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 //! //!
//! //! This library provides [`anyhow::Error`][Error], a trait object based error //! type for easy idiomatic error handling in Rust applications. //! //!
//! //! # Details //! //! - Use `Result`, or equivalently `anyhow::Result`, 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(json: &str) -> io::Result { //! # unimplemented!() //! # } //! # } //! # //! # struct ClusterMap; //! # //! # impl Deserialize for ClusterMap {} //! # //! use anyhow::Result; //! //! fn get_cluster_info() -> Result { //! 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::() { //! Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), //! None => Err(error), //! } //! # ; //! ``` //! //! - If using Rust ≥ 1.65, 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`. //! //! [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables //! //! - 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(()) //! # } //! ``` //! //!
//! //! # No-std support //! //! In no_std mode, almost all of the same API is 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.85")] #![cfg_attr(error_generic_member_access, feature(error_generic_member_access))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![no_std] #![deny(dead_code, unused_imports, unused_mut)] #![cfg_attr( not(anyhow_no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn) )] #![cfg_attr(anyhow_no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))] #![allow( clippy::doc_markdown, clippy::enum_glob_use, clippy::explicit_auto_deref, clippy::extra_unused_type_parameters, clippy::incompatible_msrv, clippy::let_underscore_untyped, 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::struct_field_names, clippy::unused_self, clippy::used_underscore_binding, clippy::wildcard_imports, clippy::wrong_self_convention )] #[cfg(all( anyhow_nightly_testing, feature = "std", not(error_generic_member_access) ))] compile_error!("Build script probe failed to compile."); extern crate alloc; #[cfg(feature = "std")] extern crate std; #[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 } } #[doc(no_inline)] pub use anyhow as format_err; /// The `Error` type, a wrapper around a dynamic error type. /// /// `Error` works a lot like `Box`, 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 — exactly one word in /// size instead of two. /// ///
/// /// # 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: ::ext_context /// at /git/anyhow/src/backtrace.rs:26 /// 1: core::result::Result::map_err /// at /git/rustc/src/libcore/result.rs:596 /// 2: anyhow::context:: for core::result::Result>::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(()) /// } /// ``` #[repr(transparent)] pub struct Error { inner: Own, } /// 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 { /// for cause in error.chain() { /// if let Some(io_error) = cause.downcast_ref::() { /// 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` /// /// 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 {...} /// // ^ equivalent to std::result::Result /// /// fn demo2() -> Result {...} /// // ^ equivalent to std::result::Result /// # }; /// ``` /// /// # Example /// /// ``` /// # pub trait Deserialize {} /// # /// # mod serde_json { /// # use super::Deserialize; /// # use std::io; /// # /// # pub fn from_str(json: &str) -> io::Result { /// # 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 = core::result::Result; /// Provides the `context` method for `Result`. /// /// This trait is sealed and cannot be implemented for types outside of /// `anyhow`. /// ///
/// /// # 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> { /// 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 /// ///
/// /// # 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::() { /// // 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::() { /// // 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: context::private::Sealed { /// Wrap the error value with additional context. fn context(self, context: C) -> Result 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(self, f: F) -> Result 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 — 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` /// --> 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`, where the type parameter `E` is specified /// ``` #[allow(non_snake_case)] pub fn Ok(t: T) -> Result { Result::Ok(t) } // Not public API. Referenced by macro-generated code. #[doc(hidden)] pub mod __private { use self::not::Bool; use crate::Error; use alloc::fmt; use core::fmt::Arguments; #[doc(hidden)] pub use crate::ensure::{BothDebug, NotBothDebug}; #[doc(hidden)] pub use alloc::format; #[doc(hidden)] pub use core::result::Result::Err; #[doc(hidden)] pub use core::{concat, format_args, stringify}; #[doc(hidden)] pub mod kind { #[doc(hidden)] pub use crate::kind::{AdhocKind, TraitKind}; #[cfg(feature = "std")] #[doc(hidden)] 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 } #[doc(hidden)] #[inline] pub fn not(cond: impl Bool) -> bool { cond.not() } mod not { #[doc(hidden)] pub trait Bool { fn not(self) -> bool; } impl Bool for bool { #[inline] fn not(self) -> bool { !self } } impl Bool for &bool { #[inline] fn not(self) -> bool { !*self } } } } anyhow-1.0.86/src/macros.rs000064400000000000000000000152401046102023000136500ustar 00000000000000/// 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)*)) }; } macro_rules! __ensure { ($ensure:item) => { /// 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(()) /// # } /// ``` $ensure }; } #[cfg(doc)] __ensure![ #[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))] __ensure![ #[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 { /// 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)*)) }; } anyhow-1.0.86/src/ptr.rs000064400000000000000000000070161046102023000131730ustar 00000000000000use alloc::boxed::Box; use core::marker::PhantomData; use core::ptr::NonNull; #[repr(transparent)] pub struct Own where T: ?Sized, { pub ptr: NonNull, } unsafe impl Send for Own where T: ?Sized {} unsafe impl Sync for Own where T: ?Sized {} impl Copy for Own where T: ?Sized {} impl Clone for Own where T: ?Sized, { fn clone(&self) -> Self { *self } } impl Own where T: ?Sized, { pub fn new(ptr: Box) -> Self { Own { ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, } } pub fn cast(self) -> Own { Own { ptr: self.ptr.cast(), } } pub unsafe fn boxed(self) -> Box { unsafe { Box::from_raw(self.ptr.as_ptr()) } } pub fn by_ref(&self) -> Ref { Ref { ptr: self.ptr, lifetime: PhantomData, } } pub fn by_mut(&mut self) -> Mut { Mut { ptr: self.ptr, lifetime: PhantomData, } } } #[repr(transparent)] pub struct Ref<'a, T> where T: ?Sized, { pub ptr: NonNull, 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) -> Self { Ref { ptr, lifetime: PhantomData, } } pub fn cast(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 { unsafe { &*self.ptr.as_ptr() } } } #[repr(transparent)] pub struct Mut<'a, T> where T: ?Sized, { pub ptr: NonNull, 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(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 { unsafe { &mut *self.ptr.as_ptr() } } } impl<'a, T> Mut<'a, T> { pub unsafe fn read(self) -> T { unsafe { self.ptr.as_ptr().read() } } } // Force turbofish on all calls of `.cast::()`. pub trait CastTo { type Target; } impl CastTo for T { type Target = T; } anyhow-1.0.86/src/wrapper.rs000064400000000000000000000033641046102023000140500ustar 00000000000000use crate::StdError; use core::fmt::{self, Debug, Display}; #[cfg(feature = "std")] use alloc::boxed::Box; #[cfg(error_generic_member_access)] use std::error::Request; #[repr(transparent)] pub struct MessageError(pub M); impl Debug for MessageError where M: Display + Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.0, f) } } impl Display for MessageError where M: Display + Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.0, f) } } impl StdError for MessageError where M: Display + Debug + 'static {} #[repr(transparent)] pub struct DisplayError(pub M); impl Debug for DisplayError where M: Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.0, f) } } impl Display for DisplayError where M: Display, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.0, f) } } impl StdError for DisplayError where M: Display + 'static {} #[cfg(feature = "std")] #[repr(transparent)] pub struct BoxedError(pub Box); #[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(error_generic_member_access)] fn provide<'a>(&'a self, request: &mut Request<'a>) { self.0.provide(request); } } anyhow-1.0.86/tests/common/mod.rs000064400000000000000000000004171046102023000150060ustar 00000000000000use 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!")); } anyhow-1.0.86/tests/compiletest.rs000064400000000000000000000002461046102023000152670ustar 00000000000000#[rustversion::attr(not(nightly), ignore)] #[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); } anyhow-1.0.86/tests/drop/mod.rs000064400000000000000000000020541046102023000144610ustar 00000000000000#![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, } 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); } } anyhow-1.0.86/tests/test_autotrait.rs000064400000000000000000000003661046102023000160150ustar 00000000000000#![allow(clippy::extra_unused_type_parameters)] use anyhow::Error; #[test] fn test_send() { fn assert_send() {} assert_send::(); } #[test] fn test_sync() { fn assert_sync() {} assert_sync::(); } anyhow-1.0.86/tests/test_backtrace.rs000064400000000000000000000004051046102023000157120ustar 00000000000000#![allow(clippy::let_underscore_untyped)] #[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(); } anyhow-1.0.86/tests/test_boxed.rs000064400000000000000000000020431046102023000150740ustar 00000000000000#![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::::from("oh no!"); let error = anyhow!(error); assert_eq!("oh no!", error.to_string()); assert_eq!( "oh no!", error .downcast_ref::>() .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()); } anyhow-1.0.86/tests/test_chain.rs000064400000000000000000000041631046102023000150620ustar 00000000000000use 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()); } anyhow-1.0.86/tests/test_context.rs000064400000000000000000000074421046102023000154670ustar 00000000000000#![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 let mid = Err::<(), LowLevel>(low) .context(MidLevel { message: "failed to load config", drop: DetectDrop::new(&dropped.mid), }) .unwrap_err(); // impl Context for Result 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::()); assert!(err.downcast_ref::().is_none()); assert!(err.is::()); let high = err.downcast_ref::().unwrap(); assert_eq!(high.to_string(), "failed to start server"); assert!(err.is::()); let mid = err.downcast_ref::().unwrap(); assert_eq!(mid.to_string(), "failed to load config"); assert!(err.is::()); let low = err.downcast_ref::().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::().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::().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::().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::().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"); } anyhow-1.0.86/tests/test_convert.rs000064400000000000000000000021751046102023000154610ustar 00000000000000#![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::::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::::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::::from(error); assert_eq!("oh no!", box_dyn.to_string()); drop(box_dyn); assert!(has_dropped.get()); } #[test] fn test_question_mark() -> Result<(), Box> { fn f() -> Result<()> { Ok(()) } f()?; Ok(()) } anyhow-1.0.86/tests/test_downcast.rs000064400000000000000000000060201046102023000156140ustar 00000000000000#![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::().unwrap(), ); assert_eq!( "oh no!", bail_error() .unwrap_err() .downcast::() .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::().unwrap(), ); assert_eq!( "oh no!", bail_error() .unwrap_err() .downcast_ref::() .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::().unwrap(), ); assert_eq!( "oh no!", bail_error() .unwrap_err() .downcast_mut::() .unwrap() .to_string(), ); let mut bailed = bail_fmt().unwrap_err(); *bailed.downcast_mut::().unwrap() = "clobber".to_string(); assert_eq!(bailed.downcast_ref::().unwrap(), "clobber"); assert_eq!(bailed.downcast_mut::().unwrap(), "clobber"); assert_eq!(bailed.downcast::().unwrap(), "clobber"); } #[test] fn test_drop() { let has_dropped = Flag::new(); let error = Error::new(DetectDrop::new(&has_dropped)); drop(error.downcast::().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::().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()); } anyhow-1.0.86/tests/test_ensure.rs000064400000000000000000000527521046102023000153100ustar 00000000000000#![allow( clippy::bool_to_int_with_if, clippy::char_lit_as_u8, clippy::deref_addrof, clippy::diverging_sub_expression, clippy::erasing_op, clippy::extra_unused_type_parameters, clippy::if_same_then_else, clippy::ifs_same_cond, clippy::ignored_unit_patterns, clippy::items_after_statements, clippy::let_and_return, clippy::let_underscore_untyped, clippy::match_bool, clippy::needless_else, clippy::never_loop, clippy::overly_complex_bool_expr, clippy::redundant_closure_call, clippy::redundant_pattern_matching, clippy::too_many_lines, clippy::unit_arg, clippy::unnecessary_cast, 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 Add 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 Trait for T {} enum Enum { #[allow(dead_code)] Thing(PhantomData), Generic, } impl PartialEq for Enum { fn eq(&self, rhs: &Self) -> bool { mem::discriminant(self) == mem::discriminant(rhs) } } impl Debug for Enum { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Generic") } } #[track_caller] fn assert_err(result: impl FnOnce() -> Result, 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 ())", ); let a = 15; let b = 3; let test = || Ok(ensure!(a <= b || a - b <= 10)); assert_err(test, "Condition failed: `a <= b || a - b <= 10`"); } #[test] fn test_high_precedence_binary_operator() { let a = 15; let b = 3; let test = || Ok(ensure!(a - b <= 10)); assert_err(test, "Condition failed: `a - b <= 10` (12 vs 10)"); } #[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::<::Owned>.t(1) == 2)); assert_err( test, "Condition failed: `Error::msg::<::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() {} 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() {} let test = || Ok(ensure!(g::() != ())); assert_err(test, "Condition failed: `g::() != ()` (() vs ())"); let test = || Ok(ensure!(g::() != ())); assert_err(test, "Condition failed: `g::() != ()` (() 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::)); assert_err(test, "Condition failed: `E::U::<> > E::U::` (U vs U)"); #[rustfmt::skip] let test = || Ok(ensure!(E::U::>E::U)); assert_err(test, "Condition failed: `E::U:: > E::U` (U vs U)"); #[rustfmt::skip] let test = || Ok(ensure!(E::U::>E::U)); assert_err(test, "Condition failed: `E::U:: > E::U` (U vs U)"); let test = || Ok(ensure!(Generic:: != Generic)); assert_err( test, "Condition failed: `Generic:: != Generic` (Generic vs Generic)", ); let test = || Ok(ensure!(Generic:: != Generic)); assert_err( test, "Condition failed: `Generic:: != Generic` (Generic vs Generic)", ); #[rustfmt::skip] let test = || { Ok(ensure!( Generic:: != Generic )) }; assert_err( test, "Condition failed: `Generic:: != 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:: {} != PhantomData)); assert_err( test, "Condition failed: `PhantomData:: {} != PhantomData` (PhantomData vs PhantomData)", ); 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::<::Owned>() == true)); assert_err( test, "Condition failed: `err.is::<::Owned>() == true` (false vs true)", ); } #[test] fn test_whitespace() { #[derive(Debug)] pub struct Point { #[allow(dead_code)] pub x: i32, #[allow(dead_code)] 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: PartialEq + Debug { type Assoc; } impl EqDebug for S where S: PartialEq + Debug, { type Assoc = bool; } let test = || Ok(ensure!(&0 as &dyn EqDebug != &0)); assert_err( test, "Condition failed: `&0 as &dyn EqDebug != &0` (0 vs 0)", ); let test = || { Ok(ensure!( PhantomData as PhantomData<::Owned> != PhantomData )) }; assert_err( test, "Condition failed: `PhantomData as PhantomData<::Owned> != PhantomData` (PhantomData vs PhantomData)", ); 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::; let test = || Ok(ensure!(if let P:: {} = p { 0 } else { 1 } == 1)); assert_err( test, "Condition failed: `if let P:: {} = 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 ::V = 0 { 0 } else { 1 } == 1)); assert_err( test, "Condition failed: `if let ::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)", ); } anyhow-1.0.86/tests/test_ffi.rs000064400000000000000000000006011046102023000145350ustar 00000000000000#![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) { *err = Some(anyhow!("ffi error")); } #[no_mangle] pub extern "C" fn anyhow3() -> Option { Some(anyhow!("ffi error")) } anyhow-1.0.86/tests/test_fmt.rs000064400000000000000000000037321046102023000145670ustar 00000000000000use 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(std_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())); } anyhow-1.0.86/tests/test_macros.rs000064400000000000000000000043311046102023000152610ustar 00000000000000#![allow( clippy::assertions_on_result_states, clippy::eq_op, clippy::incompatible_msrv, // https://github.com/rust-lang/rust-clippy/issues/12257 clippy::items_after_statements, clippy::match_single_binding, clippy::needless_pass_by_value, clippy::shadow_unrelated, clippy::wildcard_imports )] mod common; use self::common::*; use anyhow::{anyhow, ensure, Result}; 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_ensure_nonbool() -> Result<()> { struct Struct { condition: bool, } let s = Struct { condition: true }; match &s { Struct { condition } => ensure!(condition), // &bool } Ok(()) } #[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()); } anyhow-1.0.86/tests/test_repr.rs000064400000000000000000000011461046102023000147460ustar 00000000000000#![allow(clippy::extra_unused_type_parameters)] mod drop; use self::drop::{DetectDrop, Flag}; use anyhow::Error; use std::mem; #[test] fn test_error_size() { assert_eq!(mem::size_of::(), mem::size_of::()); } #[test] fn test_null_pointer_optimization() { assert_eq!(mem::size_of::>(), mem::size_of::()); } #[test] fn test_autotraits() { fn assert() {} assert::(); } #[test] fn test_drop() { let has_dropped = Flag::new(); drop(Error::new(DetectDrop::new(&has_dropped))); assert!(has_dropped.get()); } anyhow-1.0.86/tests/test_source.rs000064400000000000000000000025441046102023000153010ustar 00000000000000use 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()); } anyhow-1.0.86/tests/ui/chained-comparison.rs000064400000000000000000000003741046102023000171210ustar 00000000000000use 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(()) } anyhow-1.0.86/tests/ui/chained-comparison.stderr000064400000000000000000000004541046102023000177770ustar 00000000000000error: 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); | ++++++++ anyhow-1.0.86/tests/ui/empty-ensure.rs000064400000000000000000000001251046102023000160050ustar 00000000000000use anyhow::{ensure, Result}; fn main() -> Result<()> { ensure!(); Ok(()) } anyhow-1.0.86/tests/ui/empty-ensure.stderr000064400000000000000000000007271046102023000166740ustar 00000000000000error: 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) anyhow-1.0.86/tests/ui/ensure-nonbool.rs000064400000000000000000000011441046102023000163170ustar 00000000000000use anyhow::{ensure, Result}; use std::ops::{Deref, Not}; struct Bool(bool); struct DerefBool(bool); struct NotBool(bool); impl Deref for DerefBool { type Target = bool; fn deref(&self) -> &Self::Target { &self.0 } } impl Not for NotBool { type Output = bool; fn not(self) -> Self::Output { !self.0 } } fn main() -> Result<()> { ensure!("..."); let mut s = Bool(true); match &mut s { Bool(cond) => ensure!(cond), } let db = DerefBool(true); ensure!(db); ensure!(&db); let nb = NotBool(true); ensure!(nb); Ok(()) } anyhow-1.0.86/tests/ui/ensure-nonbool.stderr000064400000000000000000000063741046102023000172100ustar 00000000000000error[E0277]: the trait bound `&str: __private::not::Bool` is not satisfied --> tests/ui/ensure-nonbool.rs:25:13 | 25 | ensure!("..."); | --------^^^^^- | | | | | the trait `__private::not::Bool` is not implemented for `&str` | required by a bound introduced by this call | = help: the following other types implement trait `__private::not::Bool`: &bool bool note: required by a bound in `anyhow::__private::not` --> src/lib.rs | | pub fn not(cond: impl Bool) -> bool { | ^^^^ required by this bound in `not` error[E0277]: the trait bound `&mut bool: __private::not::Bool` is not satisfied --> tests/ui/ensure-nonbool.rs:29:31 | 29 | Bool(cond) => ensure!(cond), | --------^^^^- | | | | | the trait `__private::not::Bool` is not implemented for `&mut bool` | required by a bound introduced by this call | = help: the following other types implement trait `__private::not::Bool`: &bool bool = note: `__private::not::Bool` is implemented for `&bool`, but not for `&mut bool` note: required by a bound in `anyhow::__private::not` --> src/lib.rs | | pub fn not(cond: impl Bool) -> bool { | ^^^^ required by this bound in `not` error[E0277]: the trait bound `DerefBool: __private::not::Bool` is not satisfied --> tests/ui/ensure-nonbool.rs:33:13 | 33 | ensure!(db); | --------^^- | | | | | the trait `__private::not::Bool` is not implemented for `DerefBool` | required by a bound introduced by this call | = help: the following other types implement trait `__private::not::Bool`: &bool bool note: required by a bound in `anyhow::__private::not` --> src/lib.rs | | pub fn not(cond: impl Bool) -> bool { | ^^^^ required by this bound in `not` error[E0277]: the trait bound `&DerefBool: __private::not::Bool` is not satisfied --> tests/ui/ensure-nonbool.rs:34:13 | 34 | ensure!(&db); | --------^^^- | | | | | the trait `__private::not::Bool` is not implemented for `&DerefBool` | required by a bound introduced by this call | note: required by a bound in `anyhow::__private::not` --> src/lib.rs | | pub fn not(cond: impl Bool) -> bool { | ^^^^ required by this bound in `not` help: consider dereferencing here | 34 | ensure!(&*db); | + error[E0277]: the trait bound `NotBool: __private::not::Bool` is not satisfied --> tests/ui/ensure-nonbool.rs:37:13 | 37 | ensure!(nb); | --------^^- | | | | | the trait `__private::not::Bool` is not implemented for `NotBool` | required by a bound introduced by this call | = help: the following other types implement trait `__private::not::Bool`: &bool bool note: required by a bound in `anyhow::__private::not` --> src/lib.rs | | pub fn not(cond: impl Bool) -> bool { | ^^^^ required by this bound in `not` anyhow-1.0.86/tests/ui/must-use.rs000064400000000000000000000002611046102023000151330ustar 00000000000000#![deny(unused_must_use)] use anyhow::anyhow; fn main() -> anyhow::Result<()> { if true { // meant to write bail! anyhow!("it failed"); } Ok(()) } anyhow-1.0.86/tests/ui/must-use.stderr000064400000000000000000000006551046102023000160210ustar 00000000000000error: 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) anyhow-1.0.86/tests/ui/no-impl.rs000064400000000000000000000001371046102023000147260ustar 00000000000000use anyhow::anyhow; #[derive(Debug)] struct Error; fn main() { let _ = anyhow!(Error); } anyhow-1.0.86/tests/ui/no-impl.stderr000064400000000000000000000027371046102023000156150ustar 00000000000000error[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`, `Error: anyhow::kind::TraitKind` or `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` which is required by `Error: anyhow::kind::TraitKind` `Error: std::fmt::Display` which is required by `&Error: anyhow::kind::AdhocKind` `&Error: Into` 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: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `anyhow_kind`, perhaps you need to implement one of them: candidate #1: `anyhow::kind::AdhocKind` candidate #2: `anyhow::kind::BoxedKind` candidate #3: `anyhow::kind::TraitKind` = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info) anyhow-1.0.86/tests/ui/temporary-value.rs000064400000000000000000000001101046102023000164760ustar 00000000000000use anyhow::anyhow; fn main() { let _ = anyhow!(&String::new()); } anyhow-1.0.86/tests/ui/temporary-value.stderr000064400000000000000000000006501046102023000173660ustar 00000000000000error[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` anyhow-1.0.86/tests/ui/wrong-interpolation.rs000064400000000000000000000001241046102023000173700ustar 00000000000000use anyhow::{bail, Result}; fn main() -> Result<()> { bail!("{} not found"); } anyhow-1.0.86/tests/ui/wrong-interpolation.stderr000064400000000000000000000002521046102023000202510ustar 00000000000000error: 1 positional argument in format string, but no arguments were given --> tests/ui/wrong-interpolation.rs:4:12 | 4 | bail!("{} not found"); | ^^