diff --git a/Cargo.toml b/Cargo.toml index c25a387..4fa5585 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ backtrace = { version = "0.3.51", optional = true } futures = { version = "0.3", default-features = false } rustversion = "1.0.6" syn = { version = "2.0", features = ["full"] } -thiserror = "1.0" +thiserror = "1.0.45" trybuild = { version = "1.0.66", features = ["diff"] } [lib] diff --git a/build.rs b/build.rs index 3800683..de94535 100644 --- a/build.rs +++ b/build.rs @@ -11,49 +11,38 @@ compile_error! { "`backtrace` feature without `std` feature is not supported" } -// This code exercises the surface area that we expect of the std Backtrace -// type. If the current toolchain is able to compile it, we go ahead and use -// backtrace in anyhow. +// This code exercises the surface area that we expect of the Error generic +// member access API. If the current toolchain is able to compile it, then +// anyhow is able to provide backtrace support. const PROBE: &str = r#" - #![feature(error_generic_member_access, provide_any)] + #![feature(error_generic_member_access)] - use std::any::{Demand, Provider}; - use std::backtrace::{Backtrace, BacktraceStatus}; - use std::error::Error; - use std::fmt::{self, Display}; + use std::backtrace::Backtrace; + use std::error::{self, Error, Request}; + use std::fmt::{self, Debug, Display}; - #[derive(Debug)] - struct E { - backtrace: Backtrace, - } + struct MyError(Thing); + struct Thing; - impl Display for E { + impl Debug for MyError { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } } - impl Error for E { - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - demand.provide_ref(&self.backtrace); + impl Display for MyError { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() } } - struct P; - - impl Provider for P { - fn provide<'a>(&'a self, _demand: &mut Demand<'a>) {} - } - - const _: fn() = || { - let backtrace: Backtrace = Backtrace::capture(); - let status: BacktraceStatus = backtrace.status(); - match status { - BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {} + impl Error for MyError { + fn provide<'a>(&'a self, request: &mut Request<'a>) { + request.provide_ref(&self.0); } - }; + } - const _: fn(&dyn Error) -> Option<&Backtrace> = |err| err.request_ref::(); + const _: fn(&dyn Error) -> Option<&Backtrace> = |err| error::request_ref::(err); "#; fn main() { diff --git a/src/backtrace.rs b/src/backtrace.rs index 23c0c85..7c1906b 100644 --- a/src/backtrace.rs +++ b/src/backtrace.rs @@ -38,7 +38,7 @@ macro_rules! backtrace { #[cfg(backtrace)] macro_rules! backtrace_if_absent { ($err:expr) => { - match ($err as &dyn std::error::Error).request_ref::() { + match std::error::request_ref::($err as &dyn std::error::Error) { Some(_) => None, None => backtrace!(), } diff --git a/src/context.rs b/src/context.rs index 9df8693..d81b9a7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,7 +4,7 @@ use core::convert::Infallible; use core::fmt::{self, Debug, Display, Write}; #[cfg(backtrace)] -use std::any::{Demand, Provider}; +use std::error::Request; mod ext { use super::*; @@ -144,8 +144,8 @@ where } #[cfg(backtrace)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - StdError::provide(&self.error, demand); + fn provide<'a>(&'a self, request: &mut Request<'a>) { + StdError::provide(&self.error, request); } } @@ -158,8 +158,8 @@ where } #[cfg(backtrace)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - Provider::provide(&self.error, demand); + fn provide<'a>(&'a self, request: &mut Request<'a>) { + Error::provide(&self.error, request); } } diff --git a/src/error.rs b/src/error.rs index 9f6ce8c..01402d4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,14 +5,14 @@ use crate::ptr::Mut; use crate::ptr::{Own, Ref}; use crate::{Error, StdError}; use alloc::boxed::Box; -#[cfg(backtrace)] -use core::any::Demand; use core::any::TypeId; use core::fmt::{self, Debug, Display}; use core::mem::ManuallyDrop; #[cfg(not(anyhow_no_ptr_addr_of))] use core::ptr; use core::ptr::NonNull; +#[cfg(backtrace)] +use std::error::{self, Request}; #[cfg(feature = "std")] use core::ops::{Deref, DerefMut}; @@ -522,17 +522,21 @@ impl Error { Some(addr.cast::().deref_mut()) } } -} -#[cfg(backtrace)] -impl std::any::Provider for Error { + #[cfg(backtrace)] + pub(crate) fn provide<'a>(&'a self, request: &mut Request<'a>) { + unsafe { ErrorImpl::provide(self.inner.by_ref(), request) } + } + // Called by thiserror when you have `#[source] anyhow::Error`. This provide // implementation includes the anyhow::Error's Backtrace if any, unlike // deref'ing to dyn Error where the provide implementation would include // only the original error's Backtrace from before it got wrapped into an // anyhow::Error. - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - unsafe { ErrorImpl::provide(self.inner.by_ref(), demand) } + #[cfg(backtrace)] + #[doc(hidden)] + pub fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) { + Self::provide(self, request); } } @@ -900,7 +904,7 @@ impl ErrorImpl { .as_ref() .or_else(|| { #[cfg(backtrace)] - return Self::error(this).request_ref::(); + return error::request_ref::(Self::error(this)); #[cfg(not(backtrace))] return (vtable(this.ptr).object_backtrace)(this); }) @@ -908,11 +912,11 @@ impl ErrorImpl { } #[cfg(backtrace)] - unsafe fn provide<'a>(this: Ref<'a, Self>, demand: &mut Demand<'a>) { + unsafe fn provide<'a>(this: Ref<'a, Self>, request: &mut Request<'a>) { if let Some(backtrace) = &this.deref().backtrace { - demand.provide_ref(backtrace); + request.provide_ref(backtrace); } - Self::error(this).provide(demand); + Self::error(this).provide(request); } #[cold] @@ -930,8 +934,8 @@ where } #[cfg(backtrace)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - unsafe { ErrorImpl::provide(self.erase(), demand) } + fn provide<'a>(&'a self, request: &mut Request<'a>) { + unsafe { ErrorImpl::provide(self.erase(), request) } } } diff --git a/src/lib.rs b/src/lib.rs index 76f3aab..b36868f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,7 +211,7 @@ //! non-Anyhow error type inside a function that returns Anyhow's error type. #![doc(html_root_url = "https://docs.rs/anyhow/1.0.72")] -#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))] +#![cfg_attr(backtrace, feature(error_generic_member_access))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] #![deny(dead_code, unused_imports, unused_mut)] diff --git a/src/wrapper.rs b/src/wrapper.rs index 5f18a50..8a6d686 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -2,7 +2,7 @@ use crate::StdError; use core::fmt::{self, Debug, Display}; #[cfg(backtrace)] -use std::any::Demand; +use std::error::Request; #[repr(transparent)] pub struct MessageError(pub M); @@ -75,7 +75,7 @@ impl StdError for BoxedError { } #[cfg(backtrace)] - fn provide<'a>(&'a self, demand: &mut Demand<'a>) { - self.0.provide(demand); + fn provide<'a>(&'a self, request: &mut Request<'a>) { + self.0.provide(request); } }