1Anyhow ¯\\\_(°ペ)\_/¯ 2========================== 3 4[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/anyhow-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/anyhow) 5[<img alt="crates.io" src="https://img.shields.io/crates/v/anyhow.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/anyhow) 6[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-anyhow-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/anyhow) 7[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/anyhow/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster) 8 9This library provides [`anyhow::Error`][Error], a trait object based error type 10for easy idiomatic error handling in Rust applications. 11 12[Error]: https://docs.rs/anyhow/1.0/anyhow/struct.Error.html 13 14```toml 15[dependencies] 16anyhow = "1.0" 17``` 18 19*Compiler support: requires rustc 1.39+* 20 21<br> 22 23## Details 24 25- Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as the 26 return type of any fallible function. 27 28 Within the function, use `?` to easily propagate any error that implements the 29 `std::error::Error` trait. 30 31 ```rust 32 use anyhow::Result; 33 34 fn get_cluster_info() -> Result<ClusterMap> { 35 let config = std::fs::read_to_string("cluster.json")?; 36 let map: ClusterMap = serde_json::from_str(&config)?; 37 Ok(map) 38 } 39 ``` 40 41- Attach context to help the person troubleshooting the error understand where 42 things went wrong. A low-level error like "No such file or directory" can be 43 annoying to debug without more context about what higher level step the 44 application was in the middle of. 45 46 ```rust 47 use anyhow::{Context, Result}; 48 49 fn main() -> Result<()> { 50 ... 51 it.detach().context("Failed to detach the important thing")?; 52 53 let content = std::fs::read(path) 54 .with_context(|| format!("Failed to read instrs from {}", path))?; 55 ... 56 } 57 ``` 58 59 ```console 60 Error: Failed to read instrs from ./path/to/instrs.json 61 62 Caused by: 63 No such file or directory (os error 2) 64 ``` 65 66- Downcasting is supported and can be by value, by shared reference, or by 67 mutable reference as needed. 68 69 ```rust 70 // If the error was caused by redaction, then return a 71 // tombstone instead of the content. 72 match root_cause.downcast_ref::<DataStoreError>() { 73 Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), 74 None => Err(error), 75 } 76 ``` 77 78- If using Rust ≥ 1.65, a backtrace is captured and printed with the error if 79 the underlying error type does not already provide its own. In order to see 80 backtraces, they must be enabled through the environment variables described 81 in [`std::backtrace`]: 82 83 - If you want panics and errors to both have backtraces, set 84 `RUST_BACKTRACE=1`; 85 - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`; 86 - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and 87 `RUST_LIB_BACKTRACE=0`. 88 89 [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables 90 91- Anyhow works with any error type that has an impl of `std::error::Error`, 92 including ones defined in your crate. We do not bundle a `derive(Error)` macro 93 but you can write the impls yourself or use a standalone macro like 94 [thiserror]. 95 96 ```rust 97 use thiserror::Error; 98 99 #[derive(Error, Debug)] 100 pub enum FormatError { 101 #[error("Invalid header (expected {expected:?}, got {found:?})")] 102 InvalidHeader { 103 expected: String, 104 found: String, 105 }, 106 #[error("Missing attribute: {0}")] 107 MissingAttribute(String), 108 } 109 ``` 110 111- One-off error messages can be constructed using the `anyhow!` macro, which 112 supports string interpolation and produces an `anyhow::Error`. 113 114 ```rust 115 return Err(anyhow!("Missing attribute: {}", missing)); 116 ``` 117 118 A `bail!` macro is provided as a shorthand for the same early return. 119 120 ```rust 121 bail!("Missing attribute: {}", missing); 122 ``` 123 124<br> 125 126## No-std support 127 128In no_std mode, the same API is almost all available and works the same way. To 129depend on Anyhow in no_std mode, disable our default enabled "std" feature in 130Cargo.toml. A global allocator is required. 131 132```toml 133[dependencies] 134anyhow = { version = "1.0", default-features = false } 135``` 136 137Since the `?`-based error conversions would normally rely on the 138`std::error::Error` trait which is only available through std, no_std mode will 139require an explicit `.map_err(Error::msg)` when working with a non-Anyhow error 140type inside a function that returns Anyhow's error type. 141 142<br> 143 144## Comparison to failure 145 146The `anyhow::Error` type works something like `failure::Error`, but unlike 147failure ours is built around the standard library's `std::error::Error` trait 148rather than a separate trait `failure::Fail`. The standard library has adopted 149the necessary improvements for this to be possible as part of [RFC 2504]. 150 151[RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md 152 153<br> 154 155## Comparison to thiserror 156 157Use Anyhow if you don't care what error type your functions return, you just 158want it to be easy. This is common in application code. Use [thiserror] if you 159are a library that wants to design your own dedicated error type(s) so that on 160failures the caller gets exactly the information that you choose. 161 162[thiserror]: https://github.com/dtolnay/thiserror 163 164<br> 165 166#### License 167 168<sup> 169Licensed under either of <a href="LICENSE-APACHE">Apache License, Version 1702.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. 171</sup> 172 173<br> 174 175<sub> 176Unless you explicitly state otherwise, any contribution intentionally submitted 177for inclusion in this crate by you, as defined in the Apache-2.0 license, shall 178be dual licensed as above, without any additional terms or conditions. 179</sub> 180