mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-09-29 05:52:13 +00:00
make an effort at no_std support
This commit is contained in:
parent
6c1a9af5b8
commit
11757c1da5
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- 1.31.0
|
||||
- 1.34.0
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@ -29,7 +29,7 @@ jobs:
|
||||
rust:
|
||||
- stable
|
||||
- nightly
|
||||
- 1.31.0
|
||||
- 1.34.0
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@ -39,10 +39,10 @@ jobs:
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: --no-default-features
|
||||
# - uses: actions-rs/cargo@v1
|
||||
# with:
|
||||
# command: test
|
||||
# args: --no-default-features
|
||||
|
||||
fmt:
|
||||
name: Rustfmt
|
||||
@ -51,7 +51,7 @@ jobs:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- 1.31.0
|
||||
- 1.34.0
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
@ -71,7 +71,7 @@ jobs:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- 1.31.0
|
||||
- 1.34.0
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
|
@ -4,20 +4,6 @@ pub(crate) use std::backtrace::Backtrace;
|
||||
#[cfg(not(backtrace))]
|
||||
pub(crate) enum Backtrace {}
|
||||
|
||||
// #[cfg(backtrace)]
|
||||
// macro_rules! backtrace {
|
||||
// () => {
|
||||
// Some(Backtrace::capture())
|
||||
// };
|
||||
// }
|
||||
|
||||
#[cfg(not(backtrace))]
|
||||
macro_rules! backtrace {
|
||||
() => {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(backtrace)]
|
||||
macro_rules! backtrace_if_absent {
|
||||
($err:expr) => {
|
||||
@ -28,7 +14,7 @@ macro_rules! backtrace_if_absent {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", not(backtrace)))]
|
||||
#[cfg(not(backtrace))]
|
||||
macro_rules! backtrace_if_absent {
|
||||
($err:expr) => {
|
||||
None
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::error::ContextError;
|
||||
use crate::{WrapErr, ErrReport, StdError, EyreContext};
|
||||
use crate::{ErrReport, EyreContext, StdError, WrapErr};
|
||||
use core::fmt::{self, Debug, Display, Write};
|
||||
|
||||
#[cfg(backtrace)]
|
||||
|
39
src/error.rs
39
src/error.rs
@ -1,13 +1,15 @@
|
||||
use crate::alloc::Box;
|
||||
use std::any::Any;
|
||||
use crate::backtrace::Backtrace;
|
||||
use crate::chain::Chain;
|
||||
use crate::EyreContext;
|
||||
use crate::{ErrReport, StdError};
|
||||
use core::any::Any;
|
||||
use core::any::TypeId;
|
||||
use core::fmt::{self, Debug, Display};
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ptr::{self, NonNull};
|
||||
use crate::EyreContext;
|
||||
|
||||
#[cfg(backtrace)]
|
||||
use crate::backtrace::Backtrace;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use core::ops::{Deref, DerefMut};
|
||||
@ -138,9 +140,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) fn from_boxed(
|
||||
error: Box<dyn StdError + Send + Sync>,
|
||||
) -> Self {
|
||||
pub(crate) fn from_boxed(error: Box<dyn StdError + Send + Sync>) -> Self {
|
||||
use crate::wrapper::BoxedError;
|
||||
let error = BoxedError(error);
|
||||
let vtable = &ErrorVTable {
|
||||
@ -163,10 +163,7 @@ where
|
||||
//
|
||||
// Unsafe because the given vtable must have sensible behavior on the error
|
||||
// value of type E.
|
||||
unsafe fn construct<E>(
|
||||
error: E,
|
||||
vtable: &'static ErrorVTable<C>,
|
||||
) -> Self
|
||||
unsafe fn construct<E>(error: E, vtable: &'static ErrorVTable<C>) -> Self
|
||||
where
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
@ -245,10 +242,7 @@ where
|
||||
where
|
||||
D: Display + Send + Sync + 'static,
|
||||
{
|
||||
let error: ContextError<D, ErrReport<C>> = ContextError {
|
||||
msg,
|
||||
error: self,
|
||||
};
|
||||
let error: ContextError<D, ErrReport<C>> = ContextError { msg, error: self };
|
||||
|
||||
let vtable = &ErrorVTable {
|
||||
object_drop: object_drop::<ContextError<D, ErrReport<C>>, C>,
|
||||
@ -431,6 +425,10 @@ where
|
||||
Some(&mut *addr.cast::<E>().as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn context<T: Any>(&self) -> Option<&T> {
|
||||
self.inner.context()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@ -490,7 +488,7 @@ where
|
||||
|
||||
struct ErrorVTable<C>
|
||||
where
|
||||
C: EyreContext,
|
||||
C: EyreContext,
|
||||
{
|
||||
object_drop: unsafe fn(Box<ErrorImpl<(), C>>),
|
||||
object_ref: unsafe fn(&ErrorImpl<(), C>) -> &(dyn StdError + Send + Sync + 'static),
|
||||
@ -627,12 +625,14 @@ where
|
||||
D: 'static,
|
||||
{
|
||||
if TypeId::of::<D>() == target {
|
||||
let unerased = e as *const ErrorImpl<(), C> as *const ErrorImpl<ContextError<D, ErrReport<C>>, C>;
|
||||
let unerased =
|
||||
e as *const ErrorImpl<(), C> as *const ErrorImpl<ContextError<D, ErrReport<C>>, C>;
|
||||
let addr = &(*unerased)._object.msg as *const D as *mut ();
|
||||
Some(NonNull::new_unchecked(addr))
|
||||
} else {
|
||||
// Recurse down the context chain per the inner error's vtable.
|
||||
let unerased = e as *const ErrorImpl<(), C> as *const ErrorImpl<ContextError<D, ErrReport<C>>, C>;
|
||||
let unerased =
|
||||
e as *const ErrorImpl<(), C> as *const ErrorImpl<ContextError<D, ErrReport<C>>, C>;
|
||||
let source = &(*unerased)._object.error;
|
||||
(source.inner.vtable.object_downcast)(&source.inner, target)
|
||||
}
|
||||
@ -717,9 +717,10 @@ where
|
||||
unsafe { &mut *(self.vtable.object_mut)(self) }
|
||||
}
|
||||
|
||||
|
||||
pub fn context<T: Any>(&self) -> Option<&T> {
|
||||
self.context.context_raw(TypeId::of::<T>())?.downcast_ref::<T>()
|
||||
self.context
|
||||
.context_raw(TypeId::of::<T>())?
|
||||
.downcast_ref::<T>()
|
||||
}
|
||||
|
||||
#[cfg(backtrace)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::error::ErrorImpl;
|
||||
use core::fmt::{self, Write};
|
||||
use crate::EyreContext;
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
impl<C> ErrorImpl<(), C>
|
||||
where
|
||||
@ -52,6 +52,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::alloc::String;
|
||||
|
||||
#[test]
|
||||
fn one_digit() {
|
||||
|
@ -44,7 +44,7 @@
|
||||
// let error = $msg;
|
||||
// (&error).eyre_kind().new(error)
|
||||
|
||||
use crate::{EyreContext, ErrReport};
|
||||
use crate::{ErrReport, EyreContext};
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
|
63
src/lib.rs
63
src/lib.rs
@ -195,6 +195,12 @@ mod alloc {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::boxed::Box;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub use alloc::string::String;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::string::String;
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
@ -208,12 +214,11 @@ mod macros;
|
||||
mod wrapper;
|
||||
|
||||
use crate::alloc::Box;
|
||||
use crate::backtrace::Backtrace;
|
||||
use crate::error::ErrorImpl;
|
||||
use core::any::{Any, TypeId};
|
||||
use core::fmt::Display;
|
||||
use core::mem::ManuallyDrop;
|
||||
use std::backtrace::Backtrace;
|
||||
use std::any::{Any, TypeId};
|
||||
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use core::fmt::Debug;
|
||||
@ -222,7 +227,7 @@ use core::fmt::Debug;
|
||||
use std::error::Error as StdError;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
trait StdError: Debug + Display {
|
||||
pub trait StdError: Debug + Display {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
None
|
||||
}
|
||||
@ -330,26 +335,32 @@ where
|
||||
}
|
||||
|
||||
pub trait EyreContext: Sized + Send + Sync + 'static {
|
||||
fn default(err: &(dyn std::error::Error + 'static)) -> Self;
|
||||
fn default(err: &(dyn StdError + 'static)) -> Self;
|
||||
|
||||
fn context_raw(&self, typeid: TypeId) -> Option<&dyn Any>;
|
||||
|
||||
fn display(&self, error: &(dyn std::error::Error + 'static), f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
|
||||
fn display(
|
||||
&self,
|
||||
error: &(dyn StdError + 'static),
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result;
|
||||
|
||||
fn debug(&self, error: &(dyn std::error::Error + 'static), f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result;
|
||||
fn debug(
|
||||
&self,
|
||||
error: &(dyn StdError + 'static),
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result;
|
||||
}
|
||||
|
||||
pub struct DefaultContext {
|
||||
pub backtrace: Option<Backtrace>,
|
||||
backtrace: Option<Backtrace>,
|
||||
}
|
||||
|
||||
impl EyreContext for DefaultContext {
|
||||
fn default(error: &(dyn std::error::Error + 'static)) -> Self {
|
||||
fn default(_error: &(dyn StdError + 'static)) -> Self {
|
||||
let backtrace = backtrace_if_absent!(error);
|
||||
|
||||
Self {
|
||||
backtrace
|
||||
}
|
||||
Self { backtrace }
|
||||
}
|
||||
|
||||
fn context_raw(&self, typid: TypeId) -> Option<&dyn Any> {
|
||||
@ -359,11 +370,15 @@ impl EyreContext for DefaultContext {
|
||||
}
|
||||
}
|
||||
|
||||
fn display(&self, error: &(dyn std::error::Error + 'static), f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
fn display(
|
||||
&self,
|
||||
error: &(dyn StdError + 'static),
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
write!(f, "{}", error)?;
|
||||
|
||||
if f.alternate() {
|
||||
for cause in Chain::new(error).skip(1) {
|
||||
for cause in crate::chain::Chain::new(error).skip(1) {
|
||||
write!(f, ": {}", cause)?;
|
||||
}
|
||||
}
|
||||
@ -371,7 +386,11 @@ impl EyreContext for DefaultContext {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn debug(&self, error: &(dyn std::error::Error + 'static), f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
fn debug(
|
||||
&self,
|
||||
error: &(dyn StdError + 'static),
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
use core::fmt::Write as _;
|
||||
|
||||
if f.alternate() {
|
||||
@ -383,7 +402,7 @@ impl EyreContext for DefaultContext {
|
||||
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() {
|
||||
for (n, error) in crate::chain::Chain::new(cause).enumerate() {
|
||||
writeln!(f)?;
|
||||
let mut indented = fmt::Indented {
|
||||
inner: f,
|
||||
@ -398,7 +417,11 @@ impl EyreContext for DefaultContext {
|
||||
{
|
||||
use std::backtrace::BacktraceStatus;
|
||||
|
||||
let backtrace = self.backtrace.as_ref().or_else(|| error.backtrace()).expect("backtrace capture failed");
|
||||
let backtrace = self
|
||||
.backtrace
|
||||
.as_ref()
|
||||
.or_else(|| error.backtrace())
|
||||
.expect("backtrace capture failed");
|
||||
if let BacktraceStatus::Captured = backtrace.status() {
|
||||
let mut backtrace = backtrace.to_string();
|
||||
if backtrace.starts_with("stack backtrace:") {
|
||||
@ -650,11 +673,11 @@ where
|
||||
// Not public API. Referenced by macro-generated code.
|
||||
#[doc(hidden)]
|
||||
pub mod private {
|
||||
use crate::{EyreContext, ErrReport};
|
||||
use crate::{ErrReport, EyreContext};
|
||||
use core::fmt::{Debug, Display};
|
||||
|
||||
// #[cfg(backtrace)]
|
||||
// use std::backtrace::Backtrace;
|
||||
// #[cfg(backtrace)]
|
||||
// use std::backtrace::Backtrace;
|
||||
|
||||
pub use core::result::Result::Err;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use eyre::{ErrReport, eyre};
|
||||
use eyre::{eyre, ErrReport};
|
||||
use std::error::Error as StdError;
|
||||
use std::io;
|
||||
use thiserror::Error;
|
||||
|
@ -1,7 +1,7 @@
|
||||
mod drop;
|
||||
|
||||
use crate::drop::{DetectDrop, Flag};
|
||||
use eyre::{WrapErr, ErrReport, Result};
|
||||
use eyre::{ErrReport, Result, WrapErr};
|
||||
use std::fmt::{self, Display};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use eyre::{bail, WrapErr, Result};
|
||||
use eyre::{bail, Result, WrapErr};
|
||||
use std::io;
|
||||
|
||||
fn f() -> Result<()> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
mod common;
|
||||
|
||||
use self::common::*;
|
||||
use eyre::{Result, ensure};
|
||||
use eyre::{ensure, Result};
|
||||
|
||||
#[test]
|
||||
fn test_messages() {
|
||||
@ -19,13 +19,13 @@ fn test_ensure() {
|
||||
assert!(f().is_ok());
|
||||
|
||||
let v = 1;
|
||||
let f = || -> Result<()>{
|
||||
let f = || -> Result<()> {
|
||||
ensure!(v + v == 2, "This is correct, v: {}", v);
|
||||
Ok(())
|
||||
};
|
||||
assert!(f().is_ok());
|
||||
|
||||
let f = || -> Result<()>{
|
||||
let f = || -> Result<()> {
|
||||
ensure!(v + v == 1, "This is not correct, v: {}", v);
|
||||
Ok(())
|
||||
};
|
||||
|
@ -1,8 +1,8 @@
|
||||
mod drop;
|
||||
|
||||
use self::drop::{DetectDrop, Flag};
|
||||
use eyre::ErrReport;
|
||||
use eyre::DefaultContext;
|
||||
use eyre::ErrReport;
|
||||
use std::marker::Unpin;
|
||||
use std::mem;
|
||||
|
||||
@ -13,7 +13,10 @@ fn test_error_size() {
|
||||
|
||||
#[test]
|
||||
fn test_null_pointer_optimization() {
|
||||
assert_eq!(mem::size_of::<Result<(), ErrReport>>(), mem::size_of::<usize>());
|
||||
assert_eq!(
|
||||
mem::size_of::<Result<(), ErrReport>>(),
|
||||
mem::size_of::<usize>()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -25,6 +28,8 @@ fn test_autotraits() {
|
||||
#[test]
|
||||
fn test_drop() {
|
||||
let has_dropped = Flag::new();
|
||||
drop(ErrReport::<DefaultContext>::new(DetectDrop::new(&has_dropped)));
|
||||
drop(ErrReport::<DefaultContext>::new(DetectDrop::new(
|
||||
&has_dropped,
|
||||
)));
|
||||
assert!(has_dropped.get());
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use eyre::{ErrReport, eyre};
|
||||
use eyre::{eyre, ErrReport};
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt::{self, Display};
|
||||
use std::io;
|
||||
|
Loading…
x
Reference in New Issue
Block a user