Skip to content

Commit

Permalink
Merge pull request #383 from dtolnay/nostd
Browse files Browse the repository at this point in the history
Support error sources in no-std on Rust 1.81+
  • Loading branch information
dtolnay authored Sep 6, 2024
2 parents 1eabf69 + bee814a commit 8ecfcdf
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 58 deletions.
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

0 comments on commit 8ecfcdf

Please sign in to comment.