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 error sources in no-std on Rust 1.81+ #383

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [nightly, beta, stable, 1.70.0]
rust: [nightly, beta, stable, 1.80.0, 1.70.0]
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
Expand Down
7 changes: 7 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ fn main() {

if rustc >= 80 {
println!("cargo:rustc-check-cfg=cfg(anyhow_nightly_testing)");
println!("cargo:rustc-check-cfg=cfg(anyhow_no_core_error)");
println!("cargo:rustc-check-cfg=cfg(anyhow_no_fmt_arguments_as_str)");
println!("cargo:rustc-check-cfg=cfg(anyhow_no_ptr_addr_of)");
println!("cargo:rustc-check-cfg=cfg(anyhow_no_unsafe_op_in_unsafe_fn_lint)");
Expand Down Expand Up @@ -95,6 +96,12 @@ fn main() {
// https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#stabilized-apis
println!("cargo:rustc-cfg=std_backtrace");
}

if rustc < 81 {
// core::error::Error
// https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror
println!("cargo:rustc-cfg=anyhow_no_core_error");
}
}

fn compile_probe(rustc_bootstrap: bool) -> bool {
Expand Down
8 changes: 6 additions & 2 deletions src/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ macro_rules! backtrace_if_absent {
}

#[cfg(all(
feature = "std",
any(feature = "std", not(anyhow_no_core_error)),
not(error_generic_member_access),
any(std_backtrace, feature = "backtrace")
))]
Expand All @@ -57,7 +57,11 @@ macro_rules! backtrace_if_absent {
};
}

#[cfg(all(feature = "std", not(std_backtrace), not(feature = "backtrace")))]
#[cfg(all(
any(feature = "std", not(anyhow_no_core_error)),
not(std_backtrace),
not(feature = "backtrace"),
))]
macro_rules! backtrace_if_absent {
($err:expr) => {
None
Expand Down
16 changes: 8 additions & 8 deletions src/chain.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use self::ChainState::*;
use crate::StdError;

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
use alloc::vec::{self, Vec};

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
pub(crate) use crate::Chain;

#[cfg(not(feature = "std"))]
#[cfg(all(not(feature = "std"), anyhow_no_core_error))]
pub(crate) struct Chain<'a> {
state: ChainState<'a>,
}
Expand All @@ -17,7 +17,7 @@ pub(crate) enum ChainState<'a> {
Linked {
next: Option<&'a (dyn StdError + 'static)>,
},
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
Buffered {
rest: vec::IntoIter<&'a (dyn StdError + 'static)>,
},
Expand All @@ -42,7 +42,7 @@ impl<'a> Iterator for Chain<'a> {
*next = error.source();
Some(error)
}
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
Buffered { rest } => rest.next(),
}
}
Expand All @@ -53,7 +53,7 @@ impl<'a> Iterator for Chain<'a> {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl DoubleEndedIterator for Chain<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
match &mut self.state {
Expand Down Expand Up @@ -84,13 +84,13 @@ impl ExactSizeIterator for Chain<'_> {
}
len
}
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
Buffered { rest } => rest.len(),
}
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl Default for Chain<'_> {
fn default() -> Self {
Chain {
Expand Down
4 changes: 2 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ mod ext {
C: Display + Send + Sync + 'static;
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl<E> StdError for E
where
E: std::error::Error + Send + Sync + 'static,
E: crate::StdError + Send + Sync + 'static,
{
fn ext_context<C>(self, context: C) -> Error
where
Expand Down
51 changes: 22 additions & 29 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::backtrace::Backtrace;
use crate::chain::Chain;
#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(any(feature = "std", not(anyhow_no_core_error), anyhow_no_ptr_addr_of))]
use crate::ptr::Mut;
use crate::ptr::{Own, Ref};
use crate::{Error, StdError};
Expand All @@ -10,13 +10,12 @@ use core::any::TypeId;
use core::error::{self, Request};
use core::fmt::{self, Debug, Display};
use core::mem::ManuallyDrop;
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
use core::ops::{Deref, DerefMut};
#[cfg(not(anyhow_no_ptr_addr_of))]
use core::ptr;
use core::ptr::NonNull;

#[cfg(feature = "std")]
use core::ops::{Deref, DerefMut};

impl Error {
/// Create a new error object from any error type.
///
Expand All @@ -25,8 +24,7 @@ impl Error {
///
/// If the error type does not provide a backtrace, a backtrace will be
/// created here to ensure that a backtrace exists.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[cold]
#[must_use]
pub fn new<E>(error: E) -> Self
Expand Down Expand Up @@ -83,7 +81,7 @@ impl Error {
Error::from_adhoc(message, backtrace!())
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[cold]
pub(crate) fn from_std<E>(error: E, backtrace: Option<Backtrace>) -> Self
where
Expand Down Expand Up @@ -120,7 +118,7 @@ impl Error {
let vtable = &ErrorVTable {
object_drop: object_drop::<MessageError<M>>,
object_ref: object_ref::<MessageError<M>>,
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))]
object_mut: object_mut::<MessageError<M>>,
object_boxed: object_boxed::<MessageError<M>>,
object_downcast: object_downcast::<M>,
Expand Down Expand Up @@ -149,7 +147,7 @@ impl Error {
let vtable = &ErrorVTable {
object_drop: object_drop::<DisplayError<M>>,
object_ref: object_ref::<DisplayError<M>>,
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))]
object_mut: object_mut::<DisplayError<M>>,
object_boxed: object_boxed::<DisplayError<M>>,
object_downcast: object_downcast::<M>,
Expand All @@ -168,7 +166,7 @@ impl Error {
unsafe { Error::construct(error, vtable, backtrace) }
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[cold]
pub(crate) fn from_context<C, E>(context: C, error: E, backtrace: Option<Backtrace>) -> Self
where
Expand Down Expand Up @@ -198,7 +196,7 @@ impl Error {
unsafe { Error::construct(error, vtable, backtrace) }
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[cold]
pub(crate) fn from_boxed(
error: Box<dyn StdError + Send + Sync>,
Expand Down Expand Up @@ -325,7 +323,7 @@ impl Error {
let vtable = &ErrorVTable {
object_drop: object_drop::<ContextError<C, Error>>,
object_ref: object_ref::<ContextError<C, Error>>,
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))]
object_mut: object_mut::<ContextError<C, Error>>,
object_boxed: object_boxed::<ContextError<C, Error>>,
object_downcast: context_chain_downcast::<C>,
Expand Down Expand Up @@ -399,8 +397,7 @@ impl Error {
/// None
/// }
/// ```
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[cold]
pub fn chain(&self) -> Chain {
unsafe { ErrorImpl::chain(self.inner.by_ref()) }
Expand All @@ -411,8 +408,7 @@ impl Error {
///
/// The root cause is the last error in the iterator produced by
/// [`chain()`][Error::chain].
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
pub fn root_cause(&self) -> &(dyn StdError + 'static) {
self.chain().last().unwrap()
}
Expand Down Expand Up @@ -554,8 +550,7 @@ impl Error {
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl<E> From<E> for Error
where
E: StdError + Send + Sync + 'static,
Expand All @@ -567,8 +562,7 @@ where
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl Deref for Error {
type Target = dyn StdError + Send + Sync + 'static;

Expand All @@ -577,8 +571,7 @@ impl Deref for Error {
}
}

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl DerefMut for Error {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { ErrorImpl::error_mut(self.inner.by_mut()) }
Expand Down Expand Up @@ -609,7 +602,7 @@ impl Drop for Error {
struct ErrorVTable {
object_drop: unsafe fn(Own<ErrorImpl>),
object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>,
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))]
object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static),
object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>,
object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>,
Expand Down Expand Up @@ -661,7 +654,7 @@ where

// Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived
// from a `&mut`
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
#[cfg(all(any(feature = "std", not(anyhow_no_core_error)), anyhow_no_ptr_addr_of))]
unsafe fn object_mut<E>(e: Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static)
where
E: StdError + Send + Sync + 'static,
Expand Down Expand Up @@ -734,7 +727,7 @@ fn no_backtrace(e: Ref<ErrorImpl>) -> Option<&Backtrace> {
}

// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
unsafe fn context_downcast<C, E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>>
where
C: 'static,
Expand Down Expand Up @@ -774,7 +767,7 @@ where
}

// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
unsafe fn context_drop_rest<C, E>(e: Own<ErrorImpl>, target: TypeId)
where
C: 'static,
Expand Down Expand Up @@ -906,7 +899,7 @@ impl ErrorImpl {
unsafe { (vtable(this.ptr).object_ref)(this).deref() }
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
// Use vtable to attach E's native StdError vtable for the right
// original type E.
Expand Down Expand Up @@ -1009,14 +1002,14 @@ impl From<Error> for Box<dyn StdError + 'static> {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl AsRef<dyn StdError + Send + Sync> for Error {
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
&**self
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl AsRef<dyn StdError> for Error {
fn as_ref(&self) -> &(dyn StdError + 'static) {
&**self
Expand Down
12 changes: 6 additions & 6 deletions src/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
use crate::Error;
use core::fmt::{Debug, Display};

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
use crate::StdError;
#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
use alloc::boxed::Box;

pub struct Adhoc;
Expand Down Expand Up @@ -96,10 +96,10 @@ impl Trait {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
pub struct Boxed;

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
#[doc(hidden)]
pub trait BoxedKind: Sized {
#[inline]
Expand All @@ -108,10 +108,10 @@ pub trait BoxedKind: Sized {
}
}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl BoxedKind for Box<dyn StdError + Send + Sync> {}

#[cfg(feature = "std")]
#[cfg(any(feature = "std", not(anyhow_no_core_error)))]
impl Boxed {
#[cold]
pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Error {
Expand Down
Loading
Loading