Skip to content

Commit

Permalink
Merge pull request #319 from dtolnay/errorprovide
Browse files Browse the repository at this point in the history
Update to nightly's new Error::provide API
  • Loading branch information
dtolnay committed Aug 15, 2023
2 parents 496b958 + 31c8dff commit 8cf1d15
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 53 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
47 changes: 18 additions & 29 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Backtrace>();
const _: fn(&dyn Error) -> Option<&Backtrace> = |err| error::request_ref::<Backtrace>(err);
"#;

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<std::backtrace::Backtrace>() {
match std::error::request_ref::<std::backtrace::Backtrace>($err as &dyn std::error::Error) {
Some(_) => None,
None => backtrace!(),
}
Expand Down
10 changes: 5 additions & 5 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand Down
30 changes: 17 additions & 13 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -522,17 +522,21 @@ impl Error {
Some(addr.cast::<E>().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);
}
}

Expand Down Expand Up @@ -900,19 +904,19 @@ impl ErrorImpl {
.as_ref()
.or_else(|| {
#[cfg(backtrace)]
return Self::error(this).request_ref::<Backtrace>();
return error::request_ref::<Backtrace>(Self::error(this));
#[cfg(not(backtrace))]
return (vtable(this.ptr).object_backtrace)(this);
})
.expect("backtrace capture failed")
}

#[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]
Expand All @@ -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) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
6 changes: 3 additions & 3 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<M>(pub M);
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 8cf1d15

Please sign in to comment.