mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-10-02 15:26:08 +00:00
Merge remote-tracking branch 'origin/master' into color-eyre
This commit is contained in:
commit
57216d0b14
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
tags
|
||||||
|
181
CONTRIBUTING.md
Normal file
181
CONTRIBUTING.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# Welcome to the eyre contributing guide
|
||||||
|
|
||||||
|
Thank you for investing your time in contributing to our project! Eyre is a
|
||||||
|
community owned and maintained project dedicated to improving the error
|
||||||
|
handling and error reporting experience of users of the Rust programming
|
||||||
|
language.
|
||||||
|
|
||||||
|
Check out our community's[^1] [Code of
|
||||||
|
Conduct](https://www.rust-lang.org/policies/code-of-conduct) and feel free to
|
||||||
|
say hi on [Discord] if you'd like. It's a nice place to chat about eyre
|
||||||
|
development, ask questions, and get to know the other contributors and users in
|
||||||
|
a less formal setting.
|
||||||
|
|
||||||
|
## The Eyre Organization
|
||||||
|
|
||||||
|
The Eyre Organization is the group of people responsible for stewarding the
|
||||||
|
Eyre project. It handles things like merging pull requests, choosing project
|
||||||
|
direction, managing bugs / issues / feature requests, controlling access to
|
||||||
|
secrets, defining and enforcing best practices, etc.
|
||||||
|
|
||||||
|
The eyre organization's governance is based on and inspired by
|
||||||
|
[sociocracy](https://www.sociocracyforall.org/sociocracy/), the Rust Project,
|
||||||
|
and the Bevy Organization. Many thanks to their great examples and resources.
|
||||||
|
|
||||||
|
Note that you *do not* need to be a member of the Eyre Organization to
|
||||||
|
contribute to Eyre. Community contributors (this means you) can freely open
|
||||||
|
issues, submit pull requests, and review pull requests.
|
||||||
|
|
||||||
|
### New contributor guide
|
||||||
|
|
||||||
|
To get an overview of the project, read the [README](README.md). Here are some
|
||||||
|
resources to help you get started with open source contributions:
|
||||||
|
|
||||||
|
- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
|
||||||
|
- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
|
||||||
|
- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
|
||||||
|
- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
|
||||||
|
|
||||||
|
Your first PR will be merged in no time!
|
||||||
|
|
||||||
|
No matter how you're helping: thank you for contributing to Eyre!
|
||||||
|
|
||||||
|
### Classifying PRs
|
||||||
|
|
||||||
|
We use labels to organize our issues and PRs.
|
||||||
|
|
||||||
|
Each [label](https://github.com/eyre-rs/eyre/labels) has a prefix denoting its category:
|
||||||
|
|
||||||
|
* A: Area or subcrate (e.g. A-eyre, A-color-eyre, A-color-spantrace)
|
||||||
|
* C: Category (e.g. C-Breaking-Change, C-Code-Quality, C-Docs)
|
||||||
|
* P: Priority (e.g. P-Urgent, P-Important)
|
||||||
|
* S: Status (e.g. S-Blocked, S-Controversial, S-Needs-Design)
|
||||||
|
* Misc (e.g. "good first issue", "help wanted", "duplicate", "invalid", "wontfix")
|
||||||
|
|
||||||
|
## Making changes to Eyre
|
||||||
|
|
||||||
|
Most changes don't require much process. If your change is relatively straightforward, just do the following:
|
||||||
|
|
||||||
|
1. A community member (that's you!) creates one of the following:
|
||||||
|
* [GitHub Discussions]: An informal discussion with the community. This is
|
||||||
|
the place to start if you want to propose a feature or specific
|
||||||
|
implementation and gathering community wisdom and advice before jumping
|
||||||
|
to solutions.
|
||||||
|
* [Issue](https://github.com/eyre-rs/eyre/issues): A formal way for us to
|
||||||
|
track a bug or feature. Please look for duplicates before opening a new
|
||||||
|
issue and consider starting with a Discussion.
|
||||||
|
* [Pull Request](https://github.com/eyre-rs/eyre/pulls) (or PR for short):
|
||||||
|
A request to merge code changes. This starts our "review process". You
|
||||||
|
are welcome to start with a pull request, but consider starting with an
|
||||||
|
Issue or Discussion for larger changes (or if you aren't certain about a
|
||||||
|
design). We don't want anyone to waste their time on code that didn't
|
||||||
|
have a chance to be merged! But conversely, sometimes PRs are the most
|
||||||
|
efficient way to propose a change. Just use your own judgement here.
|
||||||
|
2. Other community members review and comment in an ad-hoc fashion. Active
|
||||||
|
subject matter experts may be pulled into a thread using `@mentions`. If
|
||||||
|
your PR has been quiet for a while and is ready for review, feel free to
|
||||||
|
leave a message to "bump" the thread, or bring it up on [Discord]
|
||||||
|
3. Once they're content with the pull request (design, code quality,
|
||||||
|
documentation, tests), individual reviewers leave "Approved" reviews.
|
||||||
|
4. After consensus has been reached (typically two approvals from the community
|
||||||
|
or one for extremely simple changes) and CI passes, the
|
||||||
|
[S-Ready-For-Final-Review](https://github.com/eyre-rs/eyre/issues?q=is%3Aopen+is%3Aissue+label%3AS-Ready-For-Final-Review)
|
||||||
|
label is added.
|
||||||
|
5. When they find time, someone with merge rights performs a final code review
|
||||||
|
and queue the PR for merging.
|
||||||
|
|
||||||
|
## How you can help
|
||||||
|
|
||||||
|
If you've made it to this page, you're probably already convinced that Eyre is
|
||||||
|
a project you'd like to see thrive. But how can *you* help?
|
||||||
|
|
||||||
|
No matter your experience level with Eyre or Rust or your level of commitment,
|
||||||
|
there are ways to meaningfully contribute. Take a look at the sections that
|
||||||
|
follow to pick a route (or five) that appeal to you.
|
||||||
|
|
||||||
|
If you ever find yourself at a loss for what to do, or in need of mentorship or
|
||||||
|
advice on how to contribute to Eyre, feel free to ask in [Discord] and one of
|
||||||
|
our more experienced community members will be happy to help.
|
||||||
|
|
||||||
|
### Writing Handlers
|
||||||
|
|
||||||
|
You can improve Eyre's ecosystem by building your own
|
||||||
|
[EyreHandler](https://docs.rs/eyre/0.6.8/eyre/trait.EyreHandler.html) crates
|
||||||
|
like [color-eyre](https://github.com/eyre-rs/color-eyre/). The customizable
|
||||||
|
reporting of `eyre` is it's secret sauce, using that customizability in
|
||||||
|
creative ways and sharing your work is one of the best ways you can inspire
|
||||||
|
others and help grow our community.
|
||||||
|
|
||||||
|
### Fixing bugs
|
||||||
|
|
||||||
|
Bugs in Eyre are filed on the issue tracker using the [`C-bug`](https://github.com/eyre-rs/eyre/issues?q=is%3Aissue+is%3Aopen+label%3AC-Bug) label.
|
||||||
|
|
||||||
|
If you're looking for an easy place to start, take a look at the [`good first
|
||||||
|
issue`](https://github.com/eyre-rs/eyre/labels/good%20first%20issue) label, and
|
||||||
|
feel free to ask questions on that issue's thread in question or on [Discord].
|
||||||
|
You don't need anyone's permission to try fixing a bug or adding a simple
|
||||||
|
feature, but stating that you'd like to tackle an issue can be helpful to avoid
|
||||||
|
duplicated work.
|
||||||
|
|
||||||
|
When you make a pull request that fixes an issue, include a line that says
|
||||||
|
`Fixes #X` (or "Closes"), where `X` is the issue number. This will cause the
|
||||||
|
issue in question to be closed when your PR is merged.
|
||||||
|
|
||||||
|
General improvements to code quality are also welcome!
|
||||||
|
Eyre can always be safer, better tested, and more idiomatic.
|
||||||
|
|
||||||
|
### Writing docs
|
||||||
|
|
||||||
|
This is incredibly valuable, easily distributed work, but requires a bit of guidance:
|
||||||
|
|
||||||
|
* Inaccurate documentation is worse than no documentation: prioritize fixing
|
||||||
|
broken docs.
|
||||||
|
* Code documentation (doc examples and in the examples folder) is easier to
|
||||||
|
maintain because the compiler will tell us when it breaks.
|
||||||
|
* Inline documentation should be technical and to the point. Link relevant
|
||||||
|
examples or other explanations if broader context is useful.
|
||||||
|
|
||||||
|
### Reviewing others' work
|
||||||
|
|
||||||
|
Reviewing others work with the aim of improving it is one of the most helpful
|
||||||
|
things you can do. You don't need to be an Elder Rustacean to be useful here:
|
||||||
|
anyone can catch missing tests, unclear docs, logic errors, and so on. If you
|
||||||
|
have specific skills (e.g. advanced familiarity with `unsafe` code, rendering
|
||||||
|
knowledge or web development experience) or personal experience with a problem,
|
||||||
|
try to prioritize those areas to ensure we can get appropriate expertise where
|
||||||
|
we need it.
|
||||||
|
|
||||||
|
Focus on giving constructive, actionable feedback that results in real
|
||||||
|
improvements to code quality or end-user experience. If you don't understand
|
||||||
|
why an approach was taken, please ask!
|
||||||
|
|
||||||
|
Provide actual code suggestions when that is helpful. Small changes work well
|
||||||
|
as comments or in-line suggestions on specific lines of codes. Larger changes
|
||||||
|
deserve a comment in the main thread, or a pull request to the original
|
||||||
|
author's branch (but please mention that you've made one).
|
||||||
|
|
||||||
|
Once you're happy with the work and feel you're reasonably qualified to assess
|
||||||
|
quality in this particular area, leave your `Approved` review on the PR. If
|
||||||
|
you're new to GitHub, check out the [Pull Request Review
|
||||||
|
documentation](https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews).
|
||||||
|
Anyone can leave reviews ... no special permissions are required!
|
||||||
|
|
||||||
|
There are three main places you can check for things to review:
|
||||||
|
|
||||||
|
1. Pull request which are ready and in need of more reviews on
|
||||||
|
[eyre](https://github.com/eyre-rs/eyre/pulls?q=is%3Aopen+is%3Apr+-label%3AS-Ready-For-Final-Review+-draft%3A%3Atrue+-label%3AS-Needs-RFC+-reviewed-by%3A%40me+-author%3A%40me)
|
||||||
|
2. Pull requests on [eyre](https://github.com/eyre-rs/eyre/pulls) and the
|
||||||
|
[color-eyre](https://github.com/eyre-rs/color-eyre/pulls) repos.
|
||||||
|
|
||||||
|
Not even our Circle Members are exempt from reviews! By giving feedback on this
|
||||||
|
work (and related supporting work), you can help us make sure our releases are
|
||||||
|
both high-quality and timely.
|
||||||
|
|
||||||
|
Finally, if nothing brings you more satisfaction than seeing every last issue
|
||||||
|
labeled and all resolved issues closed, feel free to message any Eyre Circle
|
||||||
|
Member (currently @yaahc) for the triage role to help us keep things tidy. This
|
||||||
|
role only requires good faith and a basic understanding of our development
|
||||||
|
process.
|
||||||
|
|
||||||
|
[Discord]: https://discord.gg/z94RqmUTKB
|
||||||
|
[^1]: Okay, I'll admit it, it's really just the Rust Project's CoC :sweat_smile:
|
36
README.md
36
README.md
@ -174,23 +174,9 @@ avoid using `eyre::Report` as your public error type.
|
|||||||
|
|
||||||
## No-std support
|
## No-std support
|
||||||
|
|
||||||
**NOTE**: tests are currently broken for `no_std` so I cannot guarantee that
|
No-std support was removed in 2020 in [commit 608a16a] due to unaddressed upstream breakages.
|
||||||
everything works still. I'm waiting for upstream fixes to be merged rather than
|
[commit 608a16a]:
|
||||||
fixing them myself, so bear with me.
|
https://github.com/eyre-rs/eyre/pull/29/commits/608a16aa2c2c27eca6c88001cc94c6973c18f1d5
|
||||||
|
|
||||||
In no_std mode, the same API is almost all available and works the same way. To
|
|
||||||
depend on Eyre in no_std mode, disable our default enabled "std" feature in
|
|
||||||
Cargo.toml. A global allocator is required.
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[dependencies]
|
|
||||||
eyre = { version = "0.6", 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(Report::msg)` when working with a non-Eyre error
|
|
||||||
type inside a function that returns Eyre's error type.
|
|
||||||
|
|
||||||
## Comparison to failure
|
## Comparison to failure
|
||||||
|
|
||||||
@ -225,24 +211,30 @@ implies that you're creating a new error that saves the old error as its
|
|||||||
`source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
|
`source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
|
||||||
being somewhat meaningless.
|
being somewhat meaningless.
|
||||||
|
|
||||||
Instead `eyre` intends for users to use the combinator functions provided by
|
Instead `eyre` offers [`OptionExt::ok_or_eyre`] to yield _static_ errors from `None`,
|
||||||
`std` for converting `Option`s to `Result`s. So where you would write this with
|
and intends for users to use the combinator functions provided by
|
||||||
|
`std`, converting `Option`s to `Result`s, for _dynamic_ errors.
|
||||||
|
So where you would write this with
|
||||||
anyhow:
|
anyhow:
|
||||||
|
|
||||||
|
[`OptionExt::ok_or_eyre`]: https://docs.rs/eyre/latest/eyre/trait.OptionExt.html#tymethod.ok_or_eyre
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
||||||
let opt: Option<()> = None;
|
let opt: Option<()> = None;
|
||||||
let result = opt.context("new error message");
|
let result_static = opt.context("static error message");
|
||||||
|
let result_dynamic = opt.with_context(|| format!("{} error message", "dynamic"));
|
||||||
```
|
```
|
||||||
|
|
||||||
With `eyre` we want users to write:
|
With `eyre` we want users to write:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use eyre::{eyre, Result};
|
use eyre::{eyre, OptionExt, Result};
|
||||||
|
|
||||||
let opt: Option<()> = None;
|
let opt: Option<()> = None;
|
||||||
let result: Result<()> = opt.ok_or_else(|| eyre!("new error message"));
|
let result_static: Result<()> = opt.ok_or_eyre("static error message");
|
||||||
|
let result_dynamic: Result<()> = opt.ok_or_else(|| eyre!("{} error message", "dynamic"));
|
||||||
```
|
```
|
||||||
|
|
||||||
**NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
|
**NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
|
||||||
|
@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased] - ReleaseDate
|
## [Unreleased] - ReleaseDate
|
||||||
|
|
||||||
|
## [0.2.1] - 2023-11-17
|
||||||
|
### Fixed
|
||||||
|
- Add license files [by erickt](https://github.com/eyre-rs/color-spantrace/pull/19)
|
||||||
|
|
||||||
## [0.2.0] - 2022-01-12
|
## [0.2.0] - 2022-01-12
|
||||||
### Changed
|
### Changed
|
||||||
- Updated dependency versions to match latest tracing versions
|
- Updated dependency versions to match latest tracing versions
|
||||||
@ -22,7 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Support custom color themes for spantrace format
|
- Support custom color themes for spantrace format
|
||||||
|
|
||||||
<!-- next-url -->
|
<!-- next-url -->
|
||||||
[Unreleased]: https://github.com/eyre-rs/color-spantrace/compare/v0.2.0...HEAD
|
[Unreleased]: https://github.com/eyre-rs/color-spantrace/compare/v0.2.1...HEAD
|
||||||
|
[0.2.1]: https://github.com/eyre-rs/color-spantrace/compare/v0.2.0...v0.2.1
|
||||||
[0.2.0]: https://github.com/eyre-rs/color-spantrace/compare/v0.1.6...v0.2.0
|
[0.2.0]: https://github.com/eyre-rs/color-spantrace/compare/v0.1.6...v0.2.0
|
||||||
[0.1.6]: https://github.com/eyre-rs/color-spantrace/compare/v0.1.5...v0.1.6
|
[0.1.6]: https://github.com/eyre-rs/color-spantrace/compare/v0.1.5...v0.1.6
|
||||||
[v0.1.5]: https://github.com/eyre-rs/color-spantrace/releases/tag/v0.1.5
|
[v0.1.5]: https://github.com/eyre-rs/color-spantrace/releases/tag/v0.1.5
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "color-spantrace"
|
name = "color-spantrace"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
description = "A pretty printer for tracing_error::SpanTrace based on color-backtrace"
|
description = "A pretty printer for tracing_error::SpanTrace based on color-backtrace"
|
||||||
documentation = "https://docs.rs/color-spantrace"
|
documentation = "https://docs.rs/color-spantrace"
|
||||||
|
|
||||||
@ -26,43 +26,5 @@ ansi-parser = "0.8" # used for testing color schemes
|
|||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[package.metadata.release]
|
[package.metadata.workspaces]
|
||||||
dev-version = false
|
independent = true
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "Unreleased"
|
|
||||||
replace="{{version}}"
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "src/lib.rs"
|
|
||||||
search = "#!\\[doc\\(html_root_url.*"
|
|
||||||
replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]"
|
|
||||||
exactly = 1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "\\.\\.\\.HEAD"
|
|
||||||
replace="...{{tag_name}}"
|
|
||||||
exactly = 1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "ReleaseDate"
|
|
||||||
replace="{{date}}"
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file="CHANGELOG.md"
|
|
||||||
search="<!-- next-header -->"
|
|
||||||
replace="<!-- next-header -->\n\n## [Unreleased] - ReleaseDate"
|
|
||||||
exactly=1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file="CHANGELOG.md"
|
|
||||||
search="<!-- next-url -->"
|
|
||||||
replace="<!-- next-url -->\n[Unreleased]: https://github.com/eyre-rs/{{crate_name}}/compare/{{tag_name}}...HEAD"
|
|
||||||
exactly=1
|
|
||||||
|
|
||||||
[[example]]
|
|
||||||
name = "color-spantrace-usage"
|
|
||||||
path = "examples/usage.rs"
|
|
||||||
|
@ -58,7 +58,7 @@ println!("{}", color_spantrace::colorize(&span_trace));
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
This example is taken from `examples/usage.rs`:
|
This example is taken from `examples/color-spantrace-usage.rs`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
53
color-spantrace/build.rs
Normal file
53
color-spantrace/build.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let version = match rustc_version_info() {
|
||||||
|
Some(version) => version,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
version.toolchain.set_feature();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum Toolchain {
|
||||||
|
Stable,
|
||||||
|
Beta,
|
||||||
|
Nightly,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Toolchain {
|
||||||
|
fn set_feature(self) {
|
||||||
|
match self {
|
||||||
|
Toolchain::Nightly => println!("cargo:rustc-cfg=nightly"),
|
||||||
|
Toolchain::Beta => println!("cargo:rustc-cfg=beta"),
|
||||||
|
Toolchain::Stable => println!("cargo:rustc-cfg=stable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VersionInfo {
|
||||||
|
toolchain: Toolchain,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rustc_version_info() -> Option<VersionInfo> {
|
||||||
|
let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("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") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let _major: u32 = pieces.next()?.parse().ok()?;
|
||||||
|
let _minor: u32 = pieces.next()?.parse().ok()?;
|
||||||
|
let _patch: u32 = pieces.next()?.parse().ok()?;
|
||||||
|
let toolchain = match pieces.next() {
|
||||||
|
Some("beta") => Toolchain::Beta,
|
||||||
|
Some("nightly") => Toolchain::Nightly,
|
||||||
|
_ => Toolchain::Stable,
|
||||||
|
};
|
||||||
|
let version = VersionInfo { toolchain };
|
||||||
|
Some(version)
|
||||||
|
}
|
@ -45,25 +45,29 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Output Format
|
//! ## Output Format
|
||||||
//!
|
//!
|
||||||
//! Running `examples/usage.rs` from the `color-spantrace` repo produces the following output:
|
//! Running `examples/color-spantrace-usage.rs` from the `color-spantrace` repo produces the following output:
|
||||||
//!
|
//!
|
||||||
//! <pre><font color="#4E9A06"><b>❯</b></font> cargo run --example usage
|
//! <pre><font color="#4E9A06"><b>❯</b></font> cargo run --example color-spantrace-usage
|
||||||
//! <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.04s
|
//! <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.04s
|
||||||
//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/usage`
|
//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/color-spantrace-usage`
|
||||||
//! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
//! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ SPANTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
//!
|
//!
|
||||||
//! 0: <font color="#F15D22">usage::two</font>
|
//! 0: <font color="#F15D22">color-spantrace-usage::two</font>
|
||||||
//! at <font color="#75507B">examples/usage.rs</font>:<font color="#75507B">18</font>
|
//! at <font color="#75507B">examples/color-spantrace-usage.rs</font>:<font color="#75507B">18</font>
|
||||||
//! 1: <font color="#F15D22">usage::one</font> with <font color="#34E2E2">i=42</font>
|
//! 1: <font color="#F15D22">color-spantrace-usage::one</font> with <font color="#34E2E2">i=42</font>
|
||||||
//! at <font color="#75507B">examples/usage.rs</font>:<font color="#75507B">13</font></pre>
|
//! at <font color="#75507B">examples/color-spantrace-usage.rs</font>:<font color="#75507B">13</font></pre>
|
||||||
//!
|
//!
|
||||||
//! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html
|
//! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html
|
||||||
//! [`color-backtrace`]: https://github.com/athre0z/color-backtrace
|
//! [`color-backtrace`]: https://github.com/athre0z/color-backtrace
|
||||||
#![doc(html_root_url = "https://docs.rs/color-spantrace/0.2.0")]
|
#![doc(html_root_url = "https://docs.rs/color-spantrace/0.2.1")]
|
||||||
|
#![cfg_attr(
|
||||||
|
nightly,
|
||||||
|
feature(rustdoc_missing_doc_code_examples),
|
||||||
|
warn(rustdoc::missing_doc_code_examples)
|
||||||
|
)]
|
||||||
#
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- one-argument ensure!($expr) [by sharnoff](https://github.com/eyre-rs/eyre/pull/86)
|
||||||
|
- documentation on the performance characteristics of `wrap_err` vs `wrap_err_with` [by akshayknarayan](https://github.com/eyre-rs/eyre/pull/93)
|
||||||
|
- tl;dr: `wrap_err_with` is faster unless the constructed error object already exists
|
||||||
|
- automated conversion to external errors for ensure! and bail! [by j-baker](https://github.com/eyre-rs/eyre/pull/95)
|
||||||
|
- eyre::Ok for generating eyre::Ok() without fully specifying the type [by kylewlacy](https://github.com/eyre-rs/eyre/pull/91)
|
||||||
|
- `OptionExt::ok_or_eyre` for yielding static `Report`s from `None` [by LeoniePhiline](https://github.com/eyre-rs/eyre/pull/125)
|
||||||
|
|
||||||
|
### New Contributors
|
||||||
|
- @sharnoff made their first contribution in https://github.com/eyre-rs/eyre/pull/86
|
||||||
|
- @akshayknarayan made their first contribution in https://github.com/eyre-rs/eyre/pull/93
|
||||||
|
- @j-baker made their first contribution in https://github.com/eyre-rs/eyre/pull/95
|
||||||
|
- @kylewlacy made their first contribution in https://github.com/eyre-rs/eyre/pull/91
|
||||||
|
- @LeoniePhiline made their first contribution in https://github.com/eyre-rs/eyre/pull/129
|
||||||
|
|
||||||
|
## [0.6.9] - 2023-11-17
|
||||||
|
### Fixed
|
||||||
|
- stacked borrows when dropping [by TimDiekmann](https://github.com/eyre-rs/eyre/pull/81)
|
||||||
|
- miri validation errors through now stricter provenance [by ten3roberts](https://github.com/eyre-rs/eyre/pull/103)
|
||||||
|
- documentation on no_std support [by thenorili](https://github.com/eyre-rs/eyre/pull/111)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- monorepo for eyre-related crates [by pksunkara](https://github.com/eyre-rs/eyre/pull/104), [[2]](https://github.com/eyre-rs/eyre/pull/105)[[3]](https://github.com/eyre-rs/eyre/pull/107)
|
||||||
|
- CONTRIBUTING.md [by yaahc](https://github.com/eyre-rs/eyre/pull/99)
|
||||||
|
|
||||||
## [0.6.8] - 2022-04-04
|
## [0.6.8] - 2022-04-04
|
||||||
### Added
|
### Added
|
||||||
- Add `#[must_use]` to `Report`
|
- `#[must_use]` to `Report`
|
||||||
- Add `must-install` feature to help reduce binary sizes when using a custom `EyreHandler`
|
- `must-install` feature to help reduce binary sizes when using a custom `EyreHandler`
|
||||||
|
|
||||||
## [0.6.7] - 2022-02-24
|
## [0.6.7] - 2022-02-24
|
||||||
### Fixed
|
### Fixed
|
||||||
- added missing track_caller annotation to new format arg capture constructor
|
- missing track_caller annotation to new format arg capture constructor
|
||||||
|
|
||||||
## [0.6.6] - 2022-01-19
|
## [0.6.6] - 2022-01-19
|
||||||
### Added
|
### Added
|
||||||
- add support for format arguments capture on 1.58 and later
|
- support for format arguments capture on 1.58 and later
|
||||||
|
|
||||||
## [0.6.5] - 2021-01-05
|
## [0.6.5] - 2021-01-05
|
||||||
### Added
|
### Added
|
||||||
- add optional support for converting into `pyo3` exceptions
|
- optional support for converting into `pyo3` exceptions
|
||||||
|
|
||||||
## [0.6.4] - 2021-01-04
|
## [0.6.4] - 2021-01-04
|
||||||
### Fixed
|
### Fixed
|
||||||
- added missing track_caller annotations to `wrap_err` related trait methods
|
- missing track_caller annotations to `wrap_err` related trait methods
|
||||||
|
|
||||||
## [0.6.3] - 2020-11-10
|
## [0.6.3] - 2020-11-10
|
||||||
### Fixed
|
### Fixed
|
||||||
- added missing track_caller annotation to autoref specialization functions
|
- missing track_caller annotation to autoref specialization functions
|
||||||
|
|
||||||
## [0.6.2] - 2020-10-27
|
## [0.6.2] - 2020-10-27
|
||||||
### Fixed
|
### Fixed
|
||||||
- added missing track_caller annotation to new_adhoc function
|
- missing track_caller annotation to new_adhoc function
|
||||||
|
|
||||||
## [0.6.1] - 2020-09-28
|
## [0.6.1] - 2020-09-28
|
||||||
### Added
|
### Added
|
||||||
- support track_caller on rust versions where it is available
|
- support for track_caller on rust versions where it is available
|
||||||
|
|
||||||
|
|
||||||
<!-- next-url -->
|
<!-- next-url -->
|
||||||
[Unreleased]: https://github.com/eyre-rs/eyre/compare/v0.6.8...HEAD
|
[Unreleased]: https://github.com/eyre-rs/eyre/compare/v0.6.10...HEAD
|
||||||
[0.6.8]: https://github.com/eyre-rs/eyre/compare/v0.6.7...v0.6.8
|
[0.6.10]: https://github.com/eyre-rs/eyre/compare/v0.6.9...v0.6.10
|
||||||
[0.6.7]: https://github.com/eyre-rs/eyre/compare/v0.6.6...v0.6.7
|
[0.6.9]: https://github.com/eyre-rs/eyre/compare/v0.6.8...v0.6.9
|
||||||
[0.6.6]: https://github.com/eyre-rs/eyre/compare/v0.6.5...v0.6.6
|
[0.6.8]: https://github.com/eyre-rs/eyre/compare/v0.6.7...v0.6.8
|
||||||
[0.6.5]: https://github.com/eyre-rs/eyre/compare/v0.6.4...v0.6.5
|
[0.6.7]: https://github.com/eyre-rs/eyre/compare/v0.6.6...v0.6.7
|
||||||
[0.6.4]: https://github.com/eyre-rs/eyre/compare/v0.6.3...v0.6.4
|
[0.6.6]: https://github.com/eyre-rs/eyre/compare/v0.6.5...v0.6.6
|
||||||
[0.6.3]: https://github.com/eyre-rs/eyre/compare/v0.6.2...v0.6.3
|
[0.6.5]: https://github.com/eyre-rs/eyre/compare/v0.6.4...v0.6.5
|
||||||
[0.6.2]: https://github.com/eyre-rs/eyre/compare/v0.6.1...v0.6.2
|
[0.6.4]: https://github.com/eyre-rs/eyre/compare/v0.6.3...v0.6.4
|
||||||
[0.6.1]: https://github.com/eyre-rs/eyre/releases/tag/v0.6.1
|
[0.6.3]: https://github.com/eyre-rs/eyre/compare/v0.6.2...v0.6.3
|
||||||
|
[0.6.2]: https://github.com/eyre-rs/eyre/compare/v0.6.1...v0.6.2
|
||||||
|
[0.6.1]: https://github.com/eyre-rs/eyre/releases/tag/v0.6.1
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "eyre"
|
name = "eyre"
|
||||||
version = "0.6.8"
|
version = "0.6.10"
|
||||||
authors = ["David Tolnay <dtolnay@gmail.com>", "Jane Lusby <jlusby42@gmail.com>"]
|
authors = ["David Tolnay <dtolnay@gmail.com>", "Jane Lusby <jlusby42@gmail.com>"]
|
||||||
description = "Flexible concrete Error Reporting type built on std::error::Error with customizable Reports"
|
description = "Flexible concrete Error Reporting type built on std::error::Error with customizable Reports"
|
||||||
documentation = "https://docs.rs/eyre"
|
documentation = "https://docs.rs/eyre"
|
||||||
@ -20,7 +20,7 @@ track-caller = []
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
indenter = { workspace = true }
|
indenter = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
pyo3 = { version = "0.13", optional = true, default-features = false }
|
pyo3 = { version = "0.20", optional = true, default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = { version = "0.3", default-features = false }
|
futures = { version = "0.3", default-features = false }
|
||||||
@ -30,45 +30,12 @@ trybuild = { version = "1.0.19", features = ["diff"] }
|
|||||||
backtrace = "0.3.46"
|
backtrace = "0.3.46"
|
||||||
anyhow = "1.0.28"
|
anyhow = "1.0.28"
|
||||||
syn = { version = "2.0", features = ["full"] }
|
syn = { version = "2.0", features = ["full"] }
|
||||||
pyo3 = { version = "0.13", default-features = false, features = ["auto-initialize"] }
|
pyo3 = { version = "0.20", default-features = false, features = ["auto-initialize"] }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
rustdoc-args = ["--cfg", "doc_cfg"]
|
rustdoc-args = ["--cfg", "doc_cfg"]
|
||||||
|
|
||||||
[package.metadata.release]
|
[package.metadata.workspaces]
|
||||||
dev-version = false
|
independent = true
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "Unreleased"
|
|
||||||
replace = "{{version}}"
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "src/lib.rs"
|
|
||||||
search = "#!\\[doc\\(html_root_url.*"
|
|
||||||
replace = "#![doc(html_root_url = \"https://docs.rs/{{crate_name}}/{{version}}\")]"
|
|
||||||
exactly = 1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "\\.\\.\\.HEAD"
|
|
||||||
replace = "...{{tag_name}}"
|
|
||||||
exactly = 1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "ReleaseDate"
|
|
||||||
replace = "{{date}}"
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "<!-- next-header -->"
|
|
||||||
replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate"
|
|
||||||
exactly = 1
|
|
||||||
|
|
||||||
[[package.metadata.release.pre-release-replacements]]
|
|
||||||
file = "CHANGELOG.md"
|
|
||||||
search = "<!-- next-url -->"
|
|
||||||
replace = "<!-- next-url -->\n[Unreleased]: https://github.com/eyre-rs/{{crate_name}}/compare/{{tag_name}}...HEAD"
|
|
||||||
exactly = 1
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, ExitStatus};
|
use std::process::{Command, ExitStatus};
|
||||||
@ -55,16 +56,18 @@ fn main() {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rustc = match rustc_minor_version() {
|
let version = match rustc_version_info() {
|
||||||
Some(rustc) => rustc,
|
Some(version) => version,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
if rustc < 52 {
|
version.toolchain.set_feature();
|
||||||
|
|
||||||
|
if version.minor < 52 {
|
||||||
println!("cargo:rustc-cfg=eyre_no_fmt_arguments_as_str");
|
println!("cargo:rustc-cfg=eyre_no_fmt_arguments_as_str");
|
||||||
}
|
}
|
||||||
|
|
||||||
if rustc < 58 {
|
if version.minor < 58 {
|
||||||
println!("cargo:rustc-cfg=eyre_no_fmt_args_capture");
|
println!("cargo:rustc-cfg=eyre_no_fmt_args_capture");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,13 +89,44 @@ fn compile_probe(probe: &str) -> Option<ExitStatus> {
|
|||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustc_minor_version() -> Option<u32> {
|
// TODO factor this toolchain parsing and related tests into its own file
|
||||||
let rustc = env::var_os("RUSTC")?;
|
#[derive(PartialEq)]
|
||||||
|
enum Toolchain {
|
||||||
|
Stable,
|
||||||
|
Beta,
|
||||||
|
Nightly,
|
||||||
|
}
|
||||||
|
impl Toolchain {
|
||||||
|
fn set_feature(self) {
|
||||||
|
match self {
|
||||||
|
Toolchain::Nightly => println!("cargo:rustc-cfg=nightly"),
|
||||||
|
Toolchain::Beta => println!("cargo:rustc-cfg=beta"),
|
||||||
|
Toolchain::Stable => println!("cargo:rustc-cfg=stable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VersionInfo {
|
||||||
|
minor: u32,
|
||||||
|
toolchain: Toolchain,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rustc_version_info() -> Option<VersionInfo> {
|
||||||
|
let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc"));
|
||||||
let output = Command::new(rustc).arg("--version").output().ok()?;
|
let output = Command::new(rustc).arg("--version").output().ok()?;
|
||||||
let version = str::from_utf8(&output.stdout).ok()?;
|
let version = str::from_utf8(&output.stdout).ok()?;
|
||||||
let mut pieces = version.split('.');
|
let mut pieces = version.split(['.', ' ', '-']);
|
||||||
if pieces.next() != Some("rustc 1") {
|
if pieces.next() != Some("rustc") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
pieces.next()?.parse().ok()
|
let _major: u32 = pieces.next()?.parse().ok()?;
|
||||||
|
let minor = pieces.next()?.parse().ok()?;
|
||||||
|
let _patch: u32 = pieces.next()?.parse().ok()?;
|
||||||
|
let toolchain = match pieces.next() {
|
||||||
|
Some("beta") => Toolchain::Beta,
|
||||||
|
Some("nightly") => Toolchain::Nightly,
|
||||||
|
_ => Toolchain::Stable,
|
||||||
|
};
|
||||||
|
let version = VersionInfo { minor, toolchain };
|
||||||
|
Some(version)
|
||||||
}
|
}
|
||||||
|
136
eyre/src/lib.rs
136
eyre/src/lib.rs
@ -236,23 +236,9 @@
|
|||||||
//!
|
//!
|
||||||
//! ## No-std support
|
//! ## No-std support
|
||||||
//!
|
//!
|
||||||
//! **NOTE**: tests are currently broken for `no_std` so I cannot guarantee that
|
//! No-std support was removed in 2020 in [commit 608a16a] due to unaddressed upstream breakages.
|
||||||
//! everything works still. I'm waiting for upstream fixes to be merged rather than
|
//! [commit 608a16a]:
|
||||||
//! fixing them myself, so bear with me.
|
//! https://github.com/eyre-rs/eyre/pull/29/commits/608a16aa2c2c27eca6c88001cc94c6973c18f1d5
|
||||||
//!
|
|
||||||
//! In no_std mode, almost all the API is available and works the same way. To
|
|
||||||
//! depend on Eyre in no_std mode, disable our default enabled "std" feature in
|
|
||||||
//! Cargo.toml. A global allocator is required.
|
|
||||||
//!
|
|
||||||
//! ```toml
|
|
||||||
//! [dependencies]
|
|
||||||
//! eyre = { version = "0.6", 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(Report::msg)` when working with a non-Eyre error
|
|
||||||
//! type inside a function that returns Eyre's error type.
|
|
||||||
//!
|
//!
|
||||||
//! ## Comparison to failure
|
//! ## Comparison to failure
|
||||||
//!
|
//!
|
||||||
@ -287,27 +273,31 @@
|
|||||||
//! `source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
|
//! `source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
|
||||||
//! being somewhat meaningless.
|
//! being somewhat meaningless.
|
||||||
//!
|
//!
|
||||||
//! Instead `eyre` intends for users to use the combinator functions provided by
|
//! Instead `eyre` offers [`OptionExt::ok_or_eyre`] to yield _static_ errors from `None`,
|
||||||
//! `std` for converting `Option`s to `Result`s. So where you would write this with
|
//! and intends for users to use the combinator functions provided by
|
||||||
|
//! `std`, converting `Option`s to `Result`s, for _dynamic_ errors.
|
||||||
|
//! So where you would write this with
|
||||||
//! anyhow:
|
//! anyhow:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use anyhow::Context;
|
//! use anyhow::Context;
|
||||||
//!
|
//!
|
||||||
//! let opt: Option<()> = None;
|
//! let opt: Option<()> = None;
|
||||||
//! let result = opt.context("new error message");
|
//! let result_static = opt.context("static error message");
|
||||||
|
//! let result_dynamic = opt.with_context(|| format!("{} error message", "dynamic"));
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! With `eyre` we want users to write:
|
//! With `eyre` we want users to write:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use eyre::{eyre, Result};
|
//! use eyre::{eyre, OptionExt, Result};
|
||||||
//!
|
//!
|
||||||
//! # #[cfg(not(feature = "auto-install"))]
|
//! # #[cfg(not(feature = "auto-install"))]
|
||||||
//! # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
|
//! # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
|
||||||
//! #
|
//! #
|
||||||
//! let opt: Option<()> = None;
|
//! let opt: Option<()> = None;
|
||||||
//! let result: Result<()> = opt.ok_or_else(|| eyre!("new error message"));
|
//! let result_static: Result<()> = opt.ok_or_eyre("static error message");
|
||||||
|
//! let result_dynamic: Result<()> = opt.ok_or_else(|| eyre!("{} error message", "dynamic"));
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! **NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
|
//! **NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
|
||||||
@ -328,12 +318,15 @@
|
|||||||
//! [`simple-eyre`]: https://github.com/eyre-rs/simple-eyre
|
//! [`simple-eyre`]: https://github.com/eyre-rs/simple-eyre
|
||||||
//! [`color-spantrace`]: https://github.com/eyre-rs/color-spantrace
|
//! [`color-spantrace`]: https://github.com/eyre-rs/color-spantrace
|
||||||
//! [`color-backtrace`]: https://github.com/athre0z/color-backtrace
|
//! [`color-backtrace`]: https://github.com/athre0z/color-backtrace
|
||||||
#![doc(html_root_url = "https://docs.rs/eyre/0.6.8")]
|
#![doc(html_root_url = "https://docs.rs/eyre/0.6.10")]
|
||||||
|
#![cfg_attr(
|
||||||
|
nightly,
|
||||||
|
feature(rustdoc_missing_doc_code_examples),
|
||||||
|
warn(rustdoc::missing_doc_code_examples)
|
||||||
|
)]
|
||||||
#![warn(
|
#![warn(
|
||||||
missing_debug_implementations,
|
missing_debug_implementations,
|
||||||
missing_docs,
|
missing_docs,
|
||||||
// FIXME: this lint is currently nightly only
|
|
||||||
rustdoc::missing_doc_code_examples,
|
|
||||||
unsafe_op_in_unsafe_fn,
|
unsafe_op_in_unsafe_fn,
|
||||||
rust_2018_idioms,
|
rust_2018_idioms,
|
||||||
unreachable_pub,
|
unreachable_pub,
|
||||||
@ -345,7 +338,6 @@
|
|||||||
overflowing_literals,
|
overflowing_literals,
|
||||||
path_statements,
|
path_statements,
|
||||||
patterns_in_fns_without_body,
|
patterns_in_fns_without_body,
|
||||||
private_in_public,
|
|
||||||
unconditional_recursion,
|
unconditional_recursion,
|
||||||
unused,
|
unused,
|
||||||
unused_allocation,
|
unused_allocation,
|
||||||
@ -371,12 +363,13 @@ mod error;
|
|||||||
mod fmt;
|
mod fmt;
|
||||||
mod kind;
|
mod kind;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
mod option;
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod wrapper;
|
mod wrapper;
|
||||||
|
|
||||||
use crate::backtrace::Backtrace;
|
use crate::backtrace::Backtrace;
|
||||||
use crate::error::ErrorImpl;
|
use crate::error::ErrorImpl;
|
||||||
use core::fmt::Display;
|
use core::fmt::{Debug, Display};
|
||||||
|
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
@ -721,7 +714,7 @@ pub trait EyreHandler: core::any::Any + Send + Sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store the location of the caller who constructed this error report
|
/// Store the location of the caller who constructed this error report
|
||||||
@ -843,7 +836,7 @@ impl EyreHandler for DefaultHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Result::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(track_caller)]
|
#[cfg(track_caller)]
|
||||||
@ -1096,6 +1089,13 @@ pub type Result<T, E = Report> = core::result::Result<T, E>;
|
|||||||
/// # panic!("expected downcast to succeed");
|
/// # panic!("expected downcast to succeed");
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// # `wrap_err` vs `wrap_err_with`
|
||||||
|
///
|
||||||
|
/// `wrap_err` incurs a runtime cost even in the non-error case because it requires eagerly
|
||||||
|
/// constructing the error object. `wrap_err_with` avoids this cost through lazy evaluation. This
|
||||||
|
/// cost is proportional to the cost of the currently installed [`EyreHandler`]'s creation step.
|
||||||
|
/// `wrap_err` is useful in cases where an constructed error object already exists.
|
||||||
pub trait WrapErr<T, E>: context::private::Sealed {
|
pub trait WrapErr<T, E>: context::private::Sealed {
|
||||||
/// Wrap the error value with a new adhoc error
|
/// Wrap the error value with a new adhoc error
|
||||||
#[cfg_attr(track_caller, track_caller)]
|
#[cfg_attr(track_caller, track_caller)]
|
||||||
@ -1125,6 +1125,61 @@ pub trait WrapErr<T, E>: context::private::Sealed {
|
|||||||
F: FnOnce() -> D;
|
F: FnOnce() -> D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Provides the [`ok_or_eyre`][OptionExt::ok_or_eyre] method for [`Option`].
|
||||||
|
///
|
||||||
|
/// This trait is sealed and cannot be implemented for types outside of
|
||||||
|
/// `eyre`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(not(feature = "auto-install"))]
|
||||||
|
/// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
|
||||||
|
/// use eyre::OptionExt;
|
||||||
|
///
|
||||||
|
/// let option: Option<()> = None;
|
||||||
|
///
|
||||||
|
/// let result = option.ok_or_eyre("static str error");
|
||||||
|
///
|
||||||
|
/// assert_eq!(result.unwrap_err().to_string(), "static str error");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # `ok_or_eyre` vs `ok_or_else`
|
||||||
|
///
|
||||||
|
/// If string interpolation is required for the generated [report][Report],
|
||||||
|
/// use [`ok_or_else`][Option::ok_or_else] instead,
|
||||||
|
/// invoking [`eyre!`] to perform string interpolation:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #[cfg(not(feature = "auto-install"))]
|
||||||
|
/// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
|
||||||
|
/// use eyre::eyre;
|
||||||
|
///
|
||||||
|
/// let option: Option<()> = None;
|
||||||
|
///
|
||||||
|
/// let result = option.ok_or_else(|| eyre!("{} error", "dynamic"));
|
||||||
|
///
|
||||||
|
/// assert_eq!(result.unwrap_err().to_string(), "dynamic error");
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// `ok_or_eyre` incurs no runtime cost, as the error object
|
||||||
|
/// is constructed from the provided static argument
|
||||||
|
/// only in the `None` case.
|
||||||
|
pub trait OptionExt<T>: context::private::Sealed {
|
||||||
|
/// Transform the [`Option<T>`] into a [`Result<T, E>`],
|
||||||
|
/// mapping [`Some(v)`][Option::Some] to [`Ok(v)`][Result::Ok]
|
||||||
|
/// and [`None`] to [`Report`].
|
||||||
|
///
|
||||||
|
/// `ok_or_eyre` allows for eyre [`Report`] error objects
|
||||||
|
/// to be lazily created from static messages in the `None` case.
|
||||||
|
///
|
||||||
|
/// For dynamic error messages, use [`ok_or_else`][Option::ok_or_else],
|
||||||
|
/// invoking [`eyre!`] in the closure to perform string interpolation.
|
||||||
|
fn ok_or_eyre<M>(self, message: M) -> crate::Result<T>
|
||||||
|
where
|
||||||
|
M: Debug + Display + Send + Sync + 'static;
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides the `context` method for `Option` when porting from `anyhow`
|
/// Provides the `context` method for `Option` when porting from `anyhow`
|
||||||
///
|
///
|
||||||
/// This trait is sealed and cannot be implemented for types outside of
|
/// This trait is sealed and cannot be implemented for types outside of
|
||||||
@ -1198,6 +1253,29 @@ pub trait ContextCompat<T>: context::private::Sealed {
|
|||||||
F: FnOnce() -> D;
|
F: FnOnce() -> D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Equivalent to Ok::<_, eyre::Error>(value).
|
||||||
|
///
|
||||||
|
/// This simplifies creation of an eyre::Result in places where type inference
|
||||||
|
/// cannot deduce the `E` type of the result — without needing to write
|
||||||
|
/// `Ok::<_, eyre::Error>(value)`.
|
||||||
|
///
|
||||||
|
/// One might think that `eyre::Result::Ok(value)` would work in such cases
|
||||||
|
/// but it does not.
|
||||||
|
///
|
||||||
|
/// ```console
|
||||||
|
/// error[E0282]: type annotations needed for `std::result::Result<i32, E>`
|
||||||
|
/// --> src/main.rs:11:13
|
||||||
|
/// |
|
||||||
|
/// 11 | let _ = eyre::Result::Ok(1);
|
||||||
|
/// | - ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||||
|
/// | |
|
||||||
|
/// | consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified
|
||||||
|
/// ```
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Ok<T>(t: T) -> Result<T> {
|
||||||
|
Result::Ok(t)
|
||||||
|
}
|
||||||
|
|
||||||
// Not public API. Referenced by macro-generated code.
|
// Not public API. Referenced by macro-generated code.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod private {
|
pub mod private {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/// Return early with an error.
|
/// Return early with an error.
|
||||||
///
|
///
|
||||||
/// This macro is equivalent to `return Err(From::from($err))`.
|
/// This macro is equivalent to `return Err(eyre!(<args>))`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -51,22 +51,22 @@
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! bail {
|
macro_rules! bail {
|
||||||
($msg:literal $(,)?) => {
|
($msg:literal $(,)?) => {
|
||||||
return $crate::private::Err($crate::eyre!($msg));
|
return $crate::private::Err($crate::eyre!($msg).into());
|
||||||
};
|
};
|
||||||
($err:expr $(,)?) => {
|
($err:expr $(,)?) => {
|
||||||
return $crate::private::Err($crate::eyre!($err));
|
return $crate::private::Err($crate::eyre!($err).into());
|
||||||
};
|
};
|
||||||
($fmt:expr, $($arg:tt)*) => {
|
($fmt:expr, $($arg:tt)*) => {
|
||||||
return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
|
return $crate::private::Err($crate::eyre!($fmt, $($arg)*).into());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return early with an error if a condition is not satisfied.
|
/// Return early with an error if a condition is not satisfied.
|
||||||
///
|
///
|
||||||
/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`.
|
/// This macro is equivalent to `if !$cond { return Err(eyre!(<other args>)); }`.
|
||||||
///
|
///
|
||||||
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
|
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
|
||||||
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error`
|
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `eyre::Result`
|
||||||
/// rather than panicking.
|
/// rather than panicking.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -107,26 +107,31 @@ macro_rules! bail {
|
|||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ensure {
|
macro_rules! ensure {
|
||||||
|
($cond:expr $(,)?) => {
|
||||||
|
if !$cond {
|
||||||
|
$crate::ensure!($cond, concat!("Condition failed: `", stringify!($cond), "`"))
|
||||||
|
}
|
||||||
|
};
|
||||||
($cond:expr, $msg:literal $(,)?) => {
|
($cond:expr, $msg:literal $(,)?) => {
|
||||||
if !$cond {
|
if !$cond {
|
||||||
return $crate::private::Err($crate::eyre!($msg));
|
return $crate::private::Err($crate::eyre!($msg).into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($cond:expr, $err:expr $(,)?) => {
|
($cond:expr, $err:expr $(,)?) => {
|
||||||
if !$cond {
|
if !$cond {
|
||||||
return $crate::private::Err($crate::eyre!($err));
|
return $crate::private::Err($crate::eyre!($err).into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($cond:expr, $fmt:expr, $($arg:tt)*) => {
|
($cond:expr, $fmt:expr, $($arg:tt)*) => {
|
||||||
if !$cond {
|
if !$cond {
|
||||||
return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
|
return $crate::private::Err($crate::eyre!($fmt, $($arg)*).into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct an ad-hoc error from a string.
|
/// Construct an ad-hoc error from a string.
|
||||||
///
|
///
|
||||||
/// This evaluates to an `Error`. It can take either just a string, or a format
|
/// This evaluates to a `Report`. It can take either just a string, or a format
|
||||||
/// string with arguments. It also can take any custom type which implements
|
/// string with arguments. It also can take any custom type which implements
|
||||||
/// `Debug` and `Display`.
|
/// `Debug` and `Display`.
|
||||||
///
|
///
|
||||||
|
14
eyre/src/option.rs
Normal file
14
eyre/src/option.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::OptionExt;
|
||||||
|
use core::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
impl<T> OptionExt<T> for Option<T> {
|
||||||
|
fn ok_or_eyre<M>(self, message: M) -> crate::Result<T>
|
||||||
|
where
|
||||||
|
M: Debug + Display + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Some(ok) => Ok(ok),
|
||||||
|
None => Err(crate::Report::msg(message)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,34 @@ fn test_ensure() {
|
|||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
assert!(f().is_err());
|
assert!(f().is_err());
|
||||||
|
|
||||||
|
// Tests single-argument `ensure!`
|
||||||
|
let f = || -> Result<()> {
|
||||||
|
ensure!(v + v == 1);
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
f().unwrap_err().to_string(),
|
||||||
|
"Condition failed: `v + v == 1`",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tests automatically converting to external errors with ensure!()
|
||||||
|
let f = || -> Result<(), SomeWrappingErr> {
|
||||||
|
ensure!(false, "this will fail");
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
assert!(f().is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct SomeWrappingErr {
|
||||||
|
err: eyre::Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<eyre::Error> for SomeWrappingErr {
|
||||||
|
fn from(err: eyre::Error) -> Self {
|
||||||
|
SomeWrappingErr { err }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
15
eyre/tests/test_option.rs
Normal file
15
eyre/tests/test_option.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
mod common;
|
||||||
|
|
||||||
|
use self::common::maybe_install_handler;
|
||||||
|
use eyre::OptionExt;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_option_ok_or_eyre() {
|
||||||
|
maybe_install_handler().unwrap();
|
||||||
|
|
||||||
|
let option: Option<()> = None;
|
||||||
|
|
||||||
|
let result = option.ok_or_eyre("static str error");
|
||||||
|
|
||||||
|
assert_eq!(result.unwrap_err().to_string(), "static str error");
|
||||||
|
}
|
@ -28,6 +28,6 @@ fn test_pyo3_exception_contents() {
|
|||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let locals = [("err", pyerr)].into_py_dict(py);
|
let locals = [("err", pyerr)].into_py_dict(py);
|
||||||
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
|
||||||
assert_eq!(pyerr.pvalue(py).to_string(), expected_contents);
|
assert_eq!(pyerr.value(py).to_string(), expected_contents);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
34
eyre/tests/test_toolchain.rs
Normal file
34
eyre/tests/test_toolchain.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// These tests check our build script against rustversion.
|
||||||
|
|
||||||
|
#[rustversion::attr(not(nightly), ignore)]
|
||||||
|
#[test]
|
||||||
|
fn nightlytest() {
|
||||||
|
if !cfg!(nightly) {
|
||||||
|
panic!("nightly feature isn't set when the toolchain is nightly.");
|
||||||
|
}
|
||||||
|
if cfg!(any(beta, stable)) {
|
||||||
|
panic!("beta, stable, and nightly are mutually exclusive features.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustversion::attr(not(beta), ignore)]
|
||||||
|
#[test]
|
||||||
|
fn betatest() {
|
||||||
|
if !cfg!(beta) {
|
||||||
|
panic!("beta feature is not set when the toolchain is beta.");
|
||||||
|
}
|
||||||
|
if cfg!(any(nightly, stable)) {
|
||||||
|
panic!("beta, stable, and nightly are mutually exclusive features.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustversion::attr(not(stable), ignore)]
|
||||||
|
#[test]
|
||||||
|
fn stabletest() {
|
||||||
|
if !cfg!(stable) {
|
||||||
|
panic!("stable feature is not set when the toolchain is stable.");
|
||||||
|
}
|
||||||
|
if cfg!(any(nightly, beta)) {
|
||||||
|
panic!("beta, stable, and nightly are mutually exclusive features.")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user