Skip to content

Commit

Permalink
Use std::backtrace::Backtrace`as the default backtrace provider
Browse files Browse the repository at this point in the history
Closes #357
  • Loading branch information
shepmaster committed Dec 4, 2023
1 parent 9bfbf49 commit cf29c73
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 258 deletions.
18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ exclude = [
]

[package.metadata.docs.rs]
# The backtraces-impl-* features are incompatible with each other
features = [ "std", "backtraces", "futures", "guide" ]
# We don't use `all-features` for a few reasons:
# - `backtraces-impl-backtrace-crate` replaces the default stdlib implementation
# - `unstable-*` features might break with little warning
# - `internal-dev-dependencies` is internal
features = ["futures", "guide"]

[features]
default = ["std", "rust_1_61"]
default = ["std", "rust_1_65"]

# Implement the `std::error::Error` trait.
std = []
Expand All @@ -37,14 +40,11 @@ unstable-core-error = []
# Add support for `Termination` for `Report`
rust_1_61 = ["snafu-derive/rust_1_61"]

# Makes the backtrace type live
backtraces = ["std", "backtrace"]
# `Backtrace` was stabilized
rust_1_65 = ["rust_1_61"]

# The backtrace type becomes `backtrace::Backtrace`
backtraces-impl-backtrace-crate = ["backtraces"]

# The backtrace type becomes `std::backtrace::Backtrace`
backtraces-impl-std = []
backtraces-impl-backtrace-crate = ["backtrace"]

# The std::error::Error provider API will be implemented.
unstable-provider-api = ["snafu-derive/unstable-provider-api"]
Expand Down
2 changes: 1 addition & 1 deletion compatibility-tests/report-provider-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
snafu = { path = "../..", features = ["backtraces-impl-std", "unstable-provider-api"] }
snafu = { path = "../..", features = ["unstable-provider-api"] }
58 changes: 58 additions & 0 deletions compatibility-tests/v1_56/src/backtraces.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use snafu::{prelude::*, Backtrace, ErrorCompat};

type AnotherError = Box<dyn std::error::Error>;

#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Invalid user {}:\n{}", user_id, backtrace))]
InvalidUser { user_id: i32, backtrace: Backtrace },
WithSource {
source: AnotherError,
backtrace: Backtrace,
},
WithSourceAndOtherInfo {
user_id: i32,
source: AnotherError,
backtrace: Backtrace,
},
}

type Result<T, E = Error> = std::result::Result<T, E>;

fn example(user_id: i32) -> Result<()> {
ensure!(user_id >= 42, InvalidUserSnafu { user_id });
Ok(())
}

#[test]
fn display_can_access_backtrace() {
let e = example(0).unwrap_err();
let text = e.to_string();
assert!(
text.contains("disabled backtrace"),
"{:?} does not contain expected text",
text
);
}

fn trigger() -> Result<(), AnotherError> {
Err("boom".into())
}

#[test]
fn errors_with_sources_can_have_backtraces() {
let e = trigger().context(WithSourceSnafu).unwrap_err();
let backtrace = ErrorCompat::backtrace(&e).unwrap();
assert!(backtrace.to_string().contains("disabled backtrace"));
}

#[test]
fn errors_with_sources_and_other_info_can_have_backtraces() {
let e = trigger()
.context(WithSourceAndOtherInfoSnafu { user_id: 42 })
.unwrap_err();
let backtrace = ErrorCompat::backtrace(&e).unwrap();
assert!(backtrace.to_string().contains("disabled backtrace"));
}

}
2 changes: 2 additions & 0 deletions compatibility-tests/v1_56/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,5 @@ mod report {
let _: Result<(), snafu::Report<Error>> = mainlike_result();
}
}

mod backtraces;
13 changes: 13 additions & 0 deletions src/backtrace_impl_backtrace_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub use backtrace::Backtrace;

impl crate::GenerateImplicitData for Backtrace {
fn generate() -> Self {
Backtrace::new()
}
}

impl crate::AsBacktrace for Backtrace {
fn as_backtrace(&self) -> Option<&Backtrace> {
Some(self)
}
}
File renamed without changes.
13 changes: 13 additions & 0 deletions src/backtrace_impl_std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub use std::backtrace::Backtrace;

impl crate::GenerateImplicitData for Backtrace {
fn generate() -> Self {
Backtrace::force_capture()
}
}

impl crate::AsBacktrace for Backtrace {
fn as_backtrace(&self) -> Option<&Backtrace> {
Some(self)
}
}
112 changes: 0 additions & 112 deletions src/backtrace_shim.rs

This file was deleted.

20 changes: 20 additions & 0 deletions src/guide/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,23 @@ and test functions.

[`Termination`]: std::process::Termination
[`Report`]: crate::Report

## `rust_1_65`

<dl class="snafu-ff-meta">
<dt>Default</dt>
<dd>enabled</dd>
<dt>Implies</dt>
<dd>

[`rust_1_61`](#rust_1_61)

</dd>
</dl>

When enabled, SNAFU will assume that it's safe to target features
available in Rust 1.65. Notably, the [`Backtrace`][] type is used when
the standard library is available and no other backtrace provider is
selected.

[`Backtrace`]: std::backtrace::Backtrace
32 changes: 15 additions & 17 deletions src/guide/examples/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,19 @@
use crate::{Snafu, Backtrace, ErrorCompat, GenerateImplicitData};

/// Backtraces aren't yet supported by the stable Rust compiler. SNAFU
/// provides a stable-compatible way of getting backtraces as well as
/// support for the backtrace support in the nightly compiler. **By
/// default, backtraces are disabled**. It is
/// expected that the final executable adds SNAFU as a dependency and
/// chooses the appropriate [feature
/// flag](crate::guide::feature_flags) to enable backtraces.
/// Rust 1.65 stabilized the [`std::backtrace::Backtrace`] type, but
/// there's not yet a stable abstraction for accessing a backtrace
/// from an arbitrary error value. SNAFU provides a stable-compatible
/// way of accessing backtraces on a SNAFU-created error type. SNAFU
/// also supports environments where backtraces are not available,
/// such as `no_std` projects.
///
/// When using SNAFU to define error types, it's recommended to start
/// with a [`Backtrace`] field on every leaf error variant (those
/// without a `source`). Backtraces are only captured on
/// failure. Since backtraces are disabled by default, adding them in
/// a library does not force any users to pay the price of backtraces
/// if they are not used; they can be zero cost.
/// When defining error types which include backtraces, it's
/// recommended to start with a [`Backtrace`] field on every leaf
/// error variant (those without a `source`). Backtraces are only
/// captured on failure.
///
/// Certain errors are used for flow control. Those don't need a
/// Certain errors are used for flow control. These don't need a
/// backtrace as they don't represent actual failures. However,
/// sometimes an error is *mostly* used for flow control but might
/// also indicate an error. In those cases, you can use
Expand All @@ -32,13 +29,13 @@ use crate::{Snafu, Backtrace, ErrorCompat, GenerateImplicitData};
/// SNAFU error, for example, you can *delegate* retrieval of the
/// backtrace to the source error. If the source error doesn't provide
/// its own backtrace, you should capture your own backtrace. This
/// backtrace would not be as useful as one captured by the source
/// backtrace will not be as useful as one captured by the source
/// error, but it's as useful as you can get.
///
/// When you wish to display the backtrace of an error, you can use
/// the [`ErrorCompat::backtrace`] method. It's recommended to always
/// use this in the fully-qualified form so it will be easy to find
/// and replace when Rust stabilizes backtraces.
/// and replace when there's a stable way to access backtraces.
///
/// ```
/// # use snafu::guide::examples::backtrace::*;
Expand All @@ -63,7 +60,8 @@ use crate::{Snafu, Backtrace, ErrorCompat, GenerateImplicitData};
// needed in most cases:
#[snafu(crate_root(crate), visibility(pub))]
pub enum Error {
/// The most common leaf error should always include a backtrace field.
/// The most common case: leaf errors should always include a
/// backtrace field.
UsualCase {
backtrace: Backtrace,
},
Expand Down
41 changes: 4 additions & 37 deletions src/guide/feature_flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ cases:
- [`std`](#std)
- [`unstable-core-error`](#unstable-core-error)
- [`guide`](#guide)
- [`backtraces`](#backtraces)
- [`backtraces-impl-backtrace-crate`](#backtraces-impl-backtrace-crate)
- [`backtraces-impl-std`](#backtraces-impl-std)
- [`unstable-provider-api`](#unstable-provider-api)
- [`futures`](#futures)
- [`unstable-try-trait`](#unstable-try-trait)
Expand Down Expand Up @@ -63,28 +61,6 @@ built.

Most usages of SNAFU will want this feature disabled.

## `backtraces`

<dl class="snafu-ff-meta">
<dt>Default</dt>
<dd>disabled</dd>
<dt>Implies</dt>
<dd>

[`std`](#std)

</dd>
</dl>
</dl>

When enabled, the [`Backtrace`] type in your enum variant will capture
a backtrace when the error is generated. If you never use backtraces,
you can omit this feature to speed up compilation a small amount.

It is recommended that only applications make use of this feature.

[`Backtrace`]: crate::Backtrace

## `backtraces-impl-backtrace-crate`

<dl class="snafu-ff-meta">
Expand All @@ -103,20 +79,11 @@ When enabled, the SNAFU [`Backtrace`] type becomes an alias to the
crates that require this type.

It is recommended that only applications make use of this
feature. When the standard library stabilizes its own backtrace type,
this feature will no longer be supported and will be removed.

## `backtraces-impl-std`
feature. When SNAFU's minimum supported Rust version has a stable
`Backtrace` type, this feature will no longer be supported and will be
removed.

<dl class="snafu-ff-meta">
<dt>Default</dt>
<dd>disabled</dd>
</dl>

When enabled, the SNAFU [`Backtrace`] type becomes an alias to the
[`std::backtrace::Backtrace`] type.

It is recommended that only applications make use of this feature.
[`Backtrace`]: crate::Backtrace

## `unstable-provider-api`

Expand Down
Loading

0 comments on commit cf29c73

Please sign in to comment.