Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support related errors in error-stack #747

Merged
merged 103 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
b47f9dd
feat: backtrace and spantrace are now saved as attachments
indietyp Jul 5, 2022
010fec0
feat: change to multiple frames
indietyp Jul 5, 2022
75ce440
feat: `add_source()`
indietyp Jul 5, 2022
8714ee0
feat: traversal implementation
indietyp Jul 5, 2022
6126e6f
chore: remove crate-local `frames()`, rename `traverse()` into `frame…
indietyp Jul 5, 2022
19044c5
fix: delay stack init in Frames
indietyp Jul 5, 2022
a2521e8
fix: `Frames` in const, through late fill
indietyp Jul 5, 2022
fff88cb
feat: Display implementation
indietyp Jul 5, 2022
5192d3f
feat: first iteration of improved renderer
indietyp Jul 5, 2022
219138a
chore: display reset
indietyp Jul 5, 2022
ea18f92
feat: redo display (WIP)
indietyp Jul 5, 2022
eab6050
feat: rework display
indietyp Jul 6, 2022
2463e89
feat: display of "Opaque" are now skipped
indietyp Jul 6, 2022
d21ed94
chore+feat: no-std imports and `sources()` function
indietyp Jul 6, 2022
2cef837
feat: reverse frame attachment in `::new()`
indietyp Jul 7, 2022
e0b8234
feat: common trait implementations
indietyp Jul 7, 2022
bc00b0b
chore: jotting down notes in `Extend`
indietyp Jul 7, 2022
a64a258
docs: feature documentation
indietyp Jul 8, 2022
4245f8e
test: fix
indietyp Jul 8, 2022
4159f59
Merge branch 'main' into main
indietyp Jul 8, 2022
10d182e
fix: merge
indietyp Jul 8, 2022
4178f00
chore: remove .idea gitignore
indietyp Jul 8, 2022
ccfb686
Merge branch 'main' into main
indietyp Jul 8, 2022
c761dcb
fix: compilation errors
indietyp Jul 8, 2022
74486b9
fix: test errors
indietyp Jul 8, 2022
5e281f3
fix: doctest
indietyp Jul 8, 2022
c534aa9
docs: note about smallvec
indietyp Jul 8, 2022
faf35b2
chore: disable all default_features
indietyp Jul 8, 2022
55920eb
fix: clippy lints
indietyp Jul 8, 2022
e4f6cae
fix: clippy lints
indietyp Jul 8, 2022
b2ac13b
fix: anyhow and eyre compat
indietyp Jul 8, 2022
d835bcd
chore: clippy
indietyp Jul 8, 2022
036ffe2
chore: remove .idea folder
indietyp Jul 8, 2022
c593110
fix: 0-based to 1-based for backtrace/spantrace output
indietyp Jul 8, 2022
06774d8
Update packages/libs/error-stack/src/lib.rs
indietyp Jul 8, 2022
0091cd0
feat: display backtrace and spantrace now defer to end
indietyp Jul 8, 2022
e332449
feat: anyhow + eyre now use attach
indietyp Jul 8, 2022
4dd95fb
chore: update .gitignore
indietyp Jul 8, 2022
9d27b08
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 8, 2022
6049098
feat: `Frame::from_compat` remove source
indietyp Jul 8, 2022
b844536
fix: spantrace not-nightly use `downcast_ref` instead
indietyp Jul 8, 2022
c794ca4
feat: SpanTrace and Backtrace now conditionally captured
indietyp Jul 8, 2022
678fe78
tst: expects_* helper now respect if able to capture
indietyp Jul 8, 2022
c653809
test: convert direct access in convert to next
indietyp Jul 8, 2022
3b9a6de
feat: rework of Iterator
indietyp Jul 8, 2022
c10c6c3
chore: rename `add_source` to `extend_one`
indietyp Jul 8, 2022
2ceefb3
feat: rework `IterMut`
indietyp Jul 9, 2022
3362b19
chore: note about request ref, delete backtrace(), spantrace() functions
indietyp Jul 9, 2022
45db0a7
chore: remove fancy output
indietyp Jul 10, 2022
62b2e64
test: conditional kinds_a
indietyp Jul 10, 2022
d30264a
fix: compat eyre,anyhow order of stmts
indietyp Jul 10, 2022
201e645
docs: `FramesMut` SAFETY
indietyp Jul 10, 2022
123f036
Merge branch 'main' into main
indietyp Jul 10, 2022
bc10e28
Apply suggestions from code review
indietyp Jul 11, 2022
86e99d5
feat: reintroduce deprecated `source(_mut)`
indietyp Jul 11, 2022
d943565
chore: combine features
indietyp Jul 11, 2022
5e7d985
feat: iter now takes slice of frames
indietyp Jul 11, 2022
bab4da1
Apply suggestions from code review
indietyp Jul 11, 2022
e021148
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 11, 2022
92a0785
feat: add deprecated `span_trace`, `backtrace` methods
indietyp Jul 11, 2022
9f74da9
feat: test for `extend_one`, clarify docstring
indietyp Jul 11, 2022
1483918
feat: display now makes use of `request_ref` and `downcast_ref`
indietyp Jul 11, 2022
2a5d691
chore: clippy
indietyp Jul 11, 2022
449312f
docs: example for backtrace and spantrace
indietyp Jul 11, 2022
c8e1c07
docs: add extending example
indietyp Jul 11, 2022
64e50ab
fix: anyhow test
indietyp Jul 11, 2022
c658567
Merge branch 'main' into main
indietyp Jul 11, 2022
25ea6f5
fix: merge impl
indietyp Jul 11, 2022
248f775
chore: enable smallvec `union`
indietyp Jul 11, 2022
9c0f04f
Merge remote-tracking branch 'original/main'
indietyp Jul 11, 2022
772b9df
fix: merge
indietyp Jul 11, 2022
5251ac2
fix: test
indietyp Jul 11, 2022
84a91f3
fix: test
indietyp Jul 11, 2022
0d9b824
fix: lints
indietyp Jul 11, 2022
3fd7315
Merge branch 'main' into main
indietyp Jul 11, 2022
c703b36
fix: imports
indietyp Jul 11, 2022
0a5d9a4
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 11, 2022
79e4d0f
fix: backtrace for anyhow and eyre
indietyp Jul 11, 2022
63fae30
Merge branch 'main' into main
indietyp Jul 11, 2022
6550c44
fix: eyre tests
indietyp Jul 11, 2022
f1d5d89
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 11, 2022
6e51164
fix: eyre
indietyp Jul 11, 2022
0bbdca6
Merge branch 'main' into main
indietyp Jul 11, 2022
25d039b
fix: cfg attach spantrace included nightly
indietyp Jul 11, 2022
098022c
fix: clippy
indietyp Jul 11, 2022
8fe7983
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 11, 2022
841d271
Apply suggestions from code review
indietyp Jul 12, 2022
a1a1ae7
feat: code review suggestions
indietyp Jul 12, 2022
791aa3a
Merge branch 'main' of github.com:indietyp/hash
indietyp Jul 12, 2022
1a6ec92
docs: alaborate on `Extend::extend_one`
indietyp Jul 12, 2022
7103f80
docs: remove miri from example
indietyp Jul 12, 2022
a8db544
test: move to `once_cell` for `supports_*`
indietyp Jul 12, 2022
3913f4e
docs: difference between `current_frames` and `current_context`
indietyp Jul 12, 2022
275d023
chore: use statements
indietyp Jul 12, 2022
a6a90c8
docs: note about `Report::new` in eyre, anyhow
indietyp Jul 12, 2022
ed5627a
docs: about assert_kinds
indietyp Jul 12, 2022
3af4778
test: implement suggestions
indietyp Jul 12, 2022
66735c6
fix: lint
indietyp Jul 12, 2022
83c75b0
Merge branch 'main' into main
indietyp Jul 12, 2022
a66089d
fix: test
indietyp Jul 12, 2022
b01ab6e
fix: doctest
indietyp Jul 12, 2022
e5e7122
Update packages/libs/error-stack/src/report.rs
indietyp Jul 12, 2022
0ac3fec
Merge branch 'main' into main
indietyp Jul 12, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions packages/libs/error-stack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ keywords = ["error", "library", "report", "no_std", "stack"]
categories = ["rust-patterns", "no-std"]

[dependencies]
tracing-error = { version = "0.2.0", optional = true }
once_cell = { version = "1.10.0", optional = true }
pin-project = { version = "1.0.10", optional = true }
tracing-error = { version = "0.2.0", optional = true, default_features = false }
once_cell = { version = "1.10.0", optional = true, default_features = false }
pin-project = { version = "1.0.10", optional = true, default_features = false }
futures-core = { version = "0.3.21", optional = true, default-features = false }
smallvec = { version = "1.9.0", optional = true, default_features = false, features = ['union'] }
anyhow = { version = "1.0.58", default-features = false, optional = true }
eyre = { version = "0.6.8", default-features = false, optional = true }

Expand All @@ -27,16 +28,18 @@ futures = { version = "0.3.21", default-features = false, features = ["executor"
trybuild = "1.0.63"
tracing = "0.1.35"
tracing-subscriber = "0.3.14"
once_cell = "1.13.0"

[build-dependencies]
rustc_version = "0.2.3"

[features]
default = ["std"]
std = ["anyhow?/std"]
default = ["std", "small"]
std = ["anyhow?/std", "once_cell?/std"]
hooks = ["dep:once_cell", "std"]
spantrace = ["dep:tracing-error"]
futures = ["dep:pin-project", "dep:futures-core"]
small = ["dep:smallvec"]

[package.metadata.docs.rs]
all-features = true
Expand Down
54 changes: 34 additions & 20 deletions packages/libs/error-stack/src/compat/anyhow.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::boxed::Box;
#[cfg(nightly)]
use core::any::Demand;
use core::{fmt, panic::Location};
Expand Down Expand Up @@ -62,33 +63,46 @@ impl<T> IntoReportCompat for core::result::Result<T, AnyhowError> {
match self {
Ok(t) => Ok(t),
Err(anyhow) => {
// we cannot use `Report::new()` directly, due to the fact that it captures traces,
// regardless of the fact if anyhow already provided one.

// only capture a backtrace if needed, otherwise the anyhow context provides one
#[cfg(all(nightly, feature = "std"))]
let backtrace = anyhow
.deref()
.backtrace()
.filter(|bt| matches!(bt.status(), std::backtrace::BacktraceStatus::Captured))
.is_none()
.then(Backtrace::capture)
.filter(|bt| matches!(bt.status(), std::backtrace::BacktraceStatus::Captured));

#[cfg(feature = "spantrace")]
let spantrace = Some(tracing_error::SpanTrace::capture())
.filter(|st| st.status() == tracing_error::SpanTraceStatus::CAPTURED);

#[cfg(feature = "std")]
let sources = anyhow
.chain()
.skip(1)
.map(ToString::to_string)
.collect::<Vec<_>>();
.collect::<alloc::vec::Vec<_>>();

#[allow(unused_mut)]
let mut report = Report::from_frame(Frame::from_context(
AnyhowContext(anyhow),
Location::caller(),
Box::new([]),
));
indietyp marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(all(nightly, feature = "std"))]
let backtrace = if anyhow
.deref()
.backtrace()
.filter(|backtrace| backtrace.status() == BacktraceStatus::Captured)
.is_some()
{
None
} else {
Some(Backtrace::capture())
};

#[cfg_attr(not(feature = "std"), allow(unused_mut))]
let mut report = Report::from_frame(
Frame::from_context(AnyhowContext(anyhow), Location::caller(), None),
#[cfg(all(nightly, feature = "std"))]
backtrace,
#[cfg(feature = "spantrace")]
Some(tracing_error::SpanTrace::capture()),
);
if let Some(backtrace) = backtrace {
report = report.attach(backtrace);
}

#[cfg(feature = "spantrace")]
if let Some(spantrace) = spantrace {
report = report.attach(spantrace);
}

#[cfg(feature = "std")]
for source in sources {
Expand Down
50 changes: 32 additions & 18 deletions packages/libs/error-stack/src/compat/eyre.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::boxed::Box;
#[cfg(nightly)]
use core::any::Demand;
use core::{fmt, panic::Location};
Expand Down Expand Up @@ -61,31 +62,44 @@ impl<T> IntoReportCompat for core::result::Result<T, EyreReport> {
match self {
Ok(t) => Ok(t),
Err(eyre) => {
// we cannot use `Report::new()` directly, due to the fact that it captures traces,
// regardless of the fact if eyre already provided one.

// only capture a backtrace if needed, otherwise the eyre context provides one
#[cfg(all(nightly, feature = "std"))]
let backtrace = eyre
.deref()
.backtrace()
.filter(|bt| matches!(bt.status(), std::backtrace::BacktraceStatus::Captured))
.is_none()
.then(Backtrace::capture)
.filter(|bt| matches!(bt.status(), std::backtrace::BacktraceStatus::Captured));

#[cfg(feature = "spantrace")]
let spantrace = Some(tracing_error::SpanTrace::capture())
.filter(|st| st.status() == tracing_error::SpanTraceStatus::CAPTURED);

let sources = eyre
.chain()
.skip(1)
.map(alloc::string::ToString::to_string)
.collect::<alloc::vec::Vec<_>>();

let mut report = Report::from_frame(Frame::from_context(
EyreContext(eyre),
Location::caller(),
Box::new([]),
));
indietyp marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(all(nightly, feature = "std"))]
let backtrace = if eyre
.deref()
.backtrace()
.filter(|backtrace| backtrace.status() == BacktraceStatus::Captured)
.is_some()
{
None
} else {
Some(Backtrace::capture())
};

let mut report = Report::from_frame(
Frame::from_context(EyreContext(eyre), Location::caller(), None),
#[cfg(all(nightly, feature = "std"))]
backtrace,
#[cfg(feature = "spantrace")]
Some(tracing_error::SpanTrace::capture()),
);
if let Some(backtrace) = backtrace {
report = report.attach(backtrace);
}

#[cfg(feature = "spantrace")]
if let Some(spantrace) = spantrace {
report = report.attach(spantrace);
}

for source in sources {
report = report.attach_printable(source);
Expand Down
1 change: 0 additions & 1 deletion packages/libs/error-stack/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ use crate::Report;
/// # #[cfg(all(feature = "std", not(miri)))]
/// # assert!(err.contains::<io::Error>());
/// # assert!(err.contains::<ConfigError>());
/// # assert_eq!(err.frames().count(), 2);
/// ```
pub trait Context: fmt::Display + fmt::Debug + Send + Sync + 'static {
/// Provide values which can then be requested by [`Report`].
Expand Down
46 changes: 23 additions & 23 deletions packages/libs/error-stack/src/frame/frame_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ pub(super) unsafe trait FrameImpl: 'static {
/// This corresponds to the `Frame` below this one in a [`Report`].
///
/// [`Report`]: crate::Report
fn source(&self) -> Option<&Frame>;
fn sources(&self) -> &[Frame];

/// Returns a mutable reference to the source of this `Frame`.
///
/// This corresponds to the `Frame` below this one in a [`Report`].
///
/// [`Report`]: crate::Report
fn source_mut(&mut self) -> Option<&mut Frame>;
fn sources_mut(&mut self) -> &mut [Frame];

/// Provide values which can then be requested.
#[cfg(nightly)]
Expand All @@ -55,7 +55,7 @@ pub(super) unsafe trait FrameImpl: 'static {
struct ContextFrame<C> {
context: C,
location: &'static Location<'static>,
source: Option<Box<Frame>>,
sources: Box<[Frame]>,
}

// SAFETY: `type_id` returns `C` and `C` is the first field in `#[repr(C)]`
Expand All @@ -72,12 +72,12 @@ unsafe impl<C: Context> FrameImpl for ContextFrame<C> {
self.location
}

fn source(&self) -> Option<&Frame> {
self.source.as_ref().map(Box::as_ref)
fn sources(&self) -> &[Frame] {
&self.sources
}

fn source_mut(&mut self) -> Option<&mut Frame> {
self.source.as_mut().map(Box::as_mut)
fn sources_mut(&mut self) -> &mut [Frame] {
&mut self.sources
}

#[cfg(nightly)]
Expand All @@ -90,7 +90,7 @@ unsafe impl<C: Context> FrameImpl for ContextFrame<C> {
struct AttachmentFrame<A> {
attachment: A,
location: &'static Location<'static>,
source: Option<Box<Frame>>,
sources: Box<[Frame]>,
}

// SAFETY: `type_id` returns `A` and `A` is the first field in `#[repr(C)]`
Expand All @@ -107,12 +107,12 @@ unsafe impl<A: 'static + Send + Sync> FrameImpl for AttachmentFrame<A> {
self.location
}

fn source(&self) -> Option<&Frame> {
self.source.as_ref().map(Box::as_ref)
fn sources(&self) -> &[Frame] {
&self.sources
}

fn source_mut(&mut self) -> Option<&mut Frame> {
self.source.as_mut().map(Box::as_mut)
fn sources_mut(&mut self) -> &mut [Frame] {
&mut self.sources
}

#[cfg(nightly)]
Expand All @@ -125,7 +125,7 @@ unsafe impl<A: 'static + Send + Sync> FrameImpl for AttachmentFrame<A> {
struct PrintableAttachmentFrame<A> {
attachment: A,
location: &'static Location<'static>,
source: Option<Box<Frame>>,
sources: Box<[Frame]>,
}

// SAFETY: `type_id` returns `A` and `A` is the first field in `#[repr(C)]`
Expand All @@ -142,12 +142,12 @@ unsafe impl<A: 'static + Debug + Display + Send + Sync> FrameImpl for PrintableA
self.location
}

fn source(&self) -> Option<&Frame> {
self.source.as_ref().map(Box::as_ref)
fn sources(&self) -> &[Frame] {
&self.sources
}

fn source_mut(&mut self) -> Option<&mut Frame> {
self.source.as_mut().map(Box::as_mut)
fn sources_mut(&mut self) -> &mut [Frame] {
&mut self.sources
}

#[cfg(nightly)]
Expand All @@ -161,7 +161,7 @@ impl Frame {
pub(crate) fn from_context<C>(
context: C,
location: &'static Location<'static>,
source: Option<Box<Self>>,
sources: Box<[Self]>,
) -> Self
where
C: Context,
Expand All @@ -170,7 +170,7 @@ impl Frame {
frame: Box::new(ContextFrame {
context,
location,
source,
sources,
}),
}
}
Expand All @@ -179,7 +179,7 @@ impl Frame {
pub(crate) fn from_attachment<A>(
attachment: A,
location: &'static Location<'static>,
source: Option<Box<Self>>,
sources: Box<[Self]>,
) -> Self
where
A: Send + Sync + 'static,
Expand All @@ -188,7 +188,7 @@ impl Frame {
frame: Box::new(AttachmentFrame {
attachment,
location,
source,
sources,
}),
}
}
Expand All @@ -200,7 +200,7 @@ impl Frame {
pub(crate) fn from_printable_attachment<A>(
attachment: A,
location: &'static Location<'static>,
source: Option<Box<Self>>,
sources: Box<[Self]>,
) -> Self
where
A: Display + Debug + Send + Sync + 'static,
Expand All @@ -209,7 +209,7 @@ impl Frame {
frame: Box::new(PrintableAttachmentFrame {
attachment,
location,
source,
sources,
}),
}
}
Expand Down
24 changes: 19 additions & 5 deletions packages/libs/error-stack/src/frame/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,38 @@ impl Frame {
self.frame.location()
}

#[allow(missing_docs)]
#[must_use]
#[deprecated = "use `sources()` instead"]
pub fn source(&self) -> Option<&Self> {
self.frame.sources().first()
}

indietyp marked this conversation as resolved.
Show resolved Hide resolved
/// Returns a shared reference to the source of this `Frame`.
///
/// This corresponds to the `Frame` below this one in a [`Report`].
///
/// [`Report`]: crate::Report
#[must_use]
pub fn source(&self) -> Option<&Self> {
self.frame.source()
pub fn sources(&self) -> &[Self] {
self.frame.sources()
indietyp marked this conversation as resolved.
Show resolved Hide resolved
}

/// Returns a mutable reference to the source of this `Frame`.
#[allow(missing_docs)]
#[must_use]
#[deprecated = "use `sources_mut()` instead"]
pub fn source_mut(&mut self) -> Option<&mut Self> {
self.frame.sources_mut().first_mut()
}
indietyp marked this conversation as resolved.
Show resolved Hide resolved

/// Returns a mutable reference to the sources of this `Frame`.
///
/// This corresponds to the `Frame` below this one in a [`Report`].
///
/// [`Report`]: crate::Report
#[must_use]
pub fn source_mut(&mut self) -> Option<&mut Self> {
self.frame.source_mut()
pub fn sources_mut(&mut self) -> &mut [Self] {
self.frame.sources_mut()
indietyp marked this conversation as resolved.
Show resolved Hide resolved
}

/// Returns how the `Frame` was created.
Expand Down
Loading