make an effort at no_std support

This commit is contained in:
Jane Lusby 2020-02-28 08:54:39 -08:00
parent 6c1a9af5b8
commit 11757c1da5
13 changed files with 91 additions and 75 deletions

View File

@ -10,7 +10,7 @@ jobs:
matrix: matrix:
rust: rust:
- stable - stable
- 1.31.0 - 1.34.0
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
@ -29,7 +29,7 @@ jobs:
rust: rust:
- stable - stable
- nightly - nightly
- 1.31.0 - 1.34.0
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
@ -39,10 +39,10 @@ jobs:
- uses: actions-rs/cargo@v1 - uses: actions-rs/cargo@v1
with: with:
command: test command: test
- uses: actions-rs/cargo@v1 # - uses: actions-rs/cargo@v1
with: # with:
command: test # command: test
args: --no-default-features # args: --no-default-features
fmt: fmt:
name: Rustfmt name: Rustfmt
@ -51,7 +51,7 @@ jobs:
matrix: matrix:
rust: rust:
- stable - stable
- 1.31.0 - 1.34.0
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
@ -71,7 +71,7 @@ jobs:
matrix: matrix:
rust: rust:
- stable - stable
- 1.31.0 - 1.34.0
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1

View File

@ -4,20 +4,6 @@ pub(crate) use std::backtrace::Backtrace;
#[cfg(not(backtrace))] #[cfg(not(backtrace))]
pub(crate) enum Backtrace {} pub(crate) enum Backtrace {}
// #[cfg(backtrace)]
// macro_rules! backtrace {
// () => {
// Some(Backtrace::capture())
// };
// }
#[cfg(not(backtrace))]
macro_rules! backtrace {
() => {
None
};
}
#[cfg(backtrace)] #[cfg(backtrace)]
macro_rules! backtrace_if_absent { macro_rules! backtrace_if_absent {
($err:expr) => { ($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 { macro_rules! backtrace_if_absent {
($err:expr) => { ($err:expr) => {
None None

View File

@ -1,5 +1,5 @@
use crate::error::ContextError; use crate::error::ContextError;
use crate::{WrapErr, ErrReport, StdError, EyreContext}; use crate::{ErrReport, EyreContext, StdError, WrapErr};
use core::fmt::{self, Debug, Display, Write}; use core::fmt::{self, Debug, Display, Write};
#[cfg(backtrace)] #[cfg(backtrace)]

View File

@ -1,13 +1,15 @@
use crate::alloc::Box; use crate::alloc::Box;
use std::any::Any;
use crate::backtrace::Backtrace;
use crate::chain::Chain; use crate::chain::Chain;
use crate::EyreContext;
use crate::{ErrReport, StdError}; use crate::{ErrReport, StdError};
use core::any::Any;
use core::any::TypeId; use core::any::TypeId;
use core::fmt::{self, Debug, Display}; use core::fmt::{self, Debug, Display};
use core::mem::{self, ManuallyDrop}; use core::mem::{self, ManuallyDrop};
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
use crate::EyreContext;
#[cfg(backtrace)]
use crate::backtrace::Backtrace;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
@ -138,9 +140,7 @@ where
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub(crate) fn from_boxed( pub(crate) fn from_boxed(error: Box<dyn StdError + Send + Sync>) -> Self {
error: Box<dyn StdError + Send + Sync>,
) -> Self {
use crate::wrapper::BoxedError; use crate::wrapper::BoxedError;
let error = BoxedError(error); let error = BoxedError(error);
let vtable = &ErrorVTable { let vtable = &ErrorVTable {
@ -163,10 +163,7 @@ where
// //
// Unsafe because the given vtable must have sensible behavior on the error // Unsafe because the given vtable must have sensible behavior on the error
// value of type E. // value of type E.
unsafe fn construct<E>( unsafe fn construct<E>(error: E, vtable: &'static ErrorVTable<C>) -> Self
error: E,
vtable: &'static ErrorVTable<C>,
) -> Self
where where
E: StdError + Send + Sync + 'static, E: StdError + Send + Sync + 'static,
{ {
@ -245,10 +242,7 @@ where
where where
D: Display + Send + Sync + 'static, D: Display + Send + Sync + 'static,
{ {
let error: ContextError<D, ErrReport<C>> = ContextError { let error: ContextError<D, ErrReport<C>> = ContextError { msg, error: self };
msg,
error: self,
};
let vtable = &ErrorVTable { let vtable = &ErrorVTable {
object_drop: object_drop::<ContextError<D, ErrReport<C>>, C>, object_drop: object_drop::<ContextError<D, ErrReport<C>>, C>,
@ -431,6 +425,10 @@ where
Some(&mut *addr.cast::<E>().as_ptr()) Some(&mut *addr.cast::<E>().as_ptr())
} }
} }
pub fn context<T: Any>(&self) -> Option<&T> {
self.inner.context()
}
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -627,12 +625,14 @@ where
D: 'static, D: 'static,
{ {
if TypeId::of::<D>() == target { 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 (); let addr = &(*unerased)._object.msg as *const D as *mut ();
Some(NonNull::new_unchecked(addr)) Some(NonNull::new_unchecked(addr))
} else { } else {
// Recurse down the context chain per the inner error's vtable. // 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; let source = &(*unerased)._object.error;
(source.inner.vtable.object_downcast)(&source.inner, target) (source.inner.vtable.object_downcast)(&source.inner, target)
} }
@ -717,9 +717,10 @@ where
unsafe { &mut *(self.vtable.object_mut)(self) } unsafe { &mut *(self.vtable.object_mut)(self) }
} }
pub fn context<T: Any>(&self) -> Option<&T> { 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)] #[cfg(backtrace)]

View File

@ -1,6 +1,6 @@
use crate::error::ErrorImpl; use crate::error::ErrorImpl;
use core::fmt::{self, Write};
use crate::EyreContext; use crate::EyreContext;
use core::fmt::{self, Write};
impl<C> ErrorImpl<(), C> impl<C> ErrorImpl<(), C>
where where
@ -52,6 +52,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::alloc::String;
#[test] #[test]
fn one_digit() { fn one_digit() {

View File

@ -44,7 +44,7 @@
// let error = $msg; // let error = $msg;
// (&error).eyre_kind().new(error) // (&error).eyre_kind().new(error)
use crate::{EyreContext, ErrReport}; use crate::{ErrReport, EyreContext};
use core::fmt::{Debug, Display}; use core::fmt::{Debug, Display};
#[cfg(feature = "std")] #[cfg(feature = "std")]

View File

@ -195,6 +195,12 @@ mod alloc {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::boxed::Box; pub use std::boxed::Box;
#[cfg(not(feature = "std"))]
pub use alloc::string::String;
#[cfg(feature = "std")]
pub use std::string::String;
} }
#[macro_use] #[macro_use]
@ -208,12 +214,11 @@ mod macros;
mod wrapper; mod wrapper;
use crate::alloc::Box; use crate::alloc::Box;
use crate::backtrace::Backtrace;
use crate::error::ErrorImpl; use crate::error::ErrorImpl;
use core::any::{Any, TypeId};
use core::fmt::Display; use core::fmt::Display;
use core::mem::ManuallyDrop; use core::mem::ManuallyDrop;
use std::backtrace::Backtrace;
use std::any::{Any, TypeId};
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use core::fmt::Debug; use core::fmt::Debug;
@ -222,7 +227,7 @@ use core::fmt::Debug;
use std::error::Error as StdError; use std::error::Error as StdError;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
trait StdError: Debug + Display { pub trait StdError: Debug + Display {
fn source(&self) -> Option<&(dyn StdError + 'static)> { fn source(&self) -> Option<&(dyn StdError + 'static)> {
None None
} }
@ -330,26 +335,32 @@ where
} }
pub trait EyreContext: Sized + Send + Sync + 'static { 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 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 struct DefaultContext {
pub backtrace: Option<Backtrace>, backtrace: Option<Backtrace>,
} }
impl EyreContext for DefaultContext { 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); let backtrace = backtrace_if_absent!(error);
Self { Self { backtrace }
backtrace
}
} }
fn context_raw(&self, typid: TypeId) -> Option<&dyn Any> { 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)?; write!(f, "{}", error)?;
if f.alternate() { if f.alternate() {
for cause in Chain::new(error).skip(1) { for cause in crate::chain::Chain::new(error).skip(1) {
write!(f, ": {}", cause)?; write!(f, ": {}", cause)?;
} }
} }
@ -371,7 +386,11 @@ impl EyreContext for DefaultContext {
Ok(()) 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 _; use core::fmt::Write as _;
if f.alternate() { if f.alternate() {
@ -383,7 +402,7 @@ impl EyreContext for DefaultContext {
if let Some(cause) = error.source() { if let Some(cause) = error.source() {
write!(f, "\n\nCaused by:")?; write!(f, "\n\nCaused by:")?;
let multiple = cause.source().is_some(); 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)?; writeln!(f)?;
let mut indented = fmt::Indented { let mut indented = fmt::Indented {
inner: f, inner: f,
@ -398,7 +417,11 @@ impl EyreContext for DefaultContext {
{ {
use std::backtrace::BacktraceStatus; 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() { if let BacktraceStatus::Captured = backtrace.status() {
let mut backtrace = backtrace.to_string(); let mut backtrace = backtrace.to_string();
if backtrace.starts_with("stack backtrace:") { if backtrace.starts_with("stack backtrace:") {
@ -650,7 +673,7 @@ where
// 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 {
use crate::{EyreContext, ErrReport}; use crate::{ErrReport, EyreContext};
use core::fmt::{Debug, Display}; use core::fmt::{Debug, Display};
// #[cfg(backtrace)] // #[cfg(backtrace)]

View File

@ -1,4 +1,4 @@
use eyre::{ErrReport, eyre}; use eyre::{eyre, ErrReport};
use std::error::Error as StdError; use std::error::Error as StdError;
use std::io; use std::io;
use thiserror::Error; use thiserror::Error;

View File

@ -1,7 +1,7 @@
mod drop; mod drop;
use crate::drop::{DetectDrop, Flag}; use crate::drop::{DetectDrop, Flag};
use eyre::{WrapErr, ErrReport, Result}; use eyre::{ErrReport, Result, WrapErr};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use thiserror::Error; use thiserror::Error;

View File

@ -1,4 +1,4 @@
use eyre::{bail, WrapErr, Result}; use eyre::{bail, Result, WrapErr};
use std::io; use std::io;
fn f() -> Result<()> { fn f() -> Result<()> {

View File

@ -1,7 +1,7 @@
mod common; mod common;
use self::common::*; use self::common::*;
use eyre::{Result, ensure}; use eyre::{ensure, Result};
#[test] #[test]
fn test_messages() { fn test_messages() {

View File

@ -1,8 +1,8 @@
mod drop; mod drop;
use self::drop::{DetectDrop, Flag}; use self::drop::{DetectDrop, Flag};
use eyre::ErrReport;
use eyre::DefaultContext; use eyre::DefaultContext;
use eyre::ErrReport;
use std::marker::Unpin; use std::marker::Unpin;
use std::mem; use std::mem;
@ -13,7 +13,10 @@ fn test_error_size() {
#[test] #[test]
fn test_null_pointer_optimization() { 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] #[test]
@ -25,6 +28,8 @@ fn test_autotraits() {
#[test] #[test]
fn test_drop() { fn test_drop() {
let has_dropped = Flag::new(); 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()); assert!(has_dropped.get());
} }

View File

@ -1,4 +1,4 @@
use eyre::{ErrReport, eyre}; use eyre::{eyre, ErrReport};
use std::error::Error as StdError; use std::error::Error as StdError;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use std::io; use std::io;